From e453564eb17e43ba70036a8093eb1f8063eaddc7 Mon Sep 17 00:00:00 2001 From: JordiSubira Date: Wed, 25 Jan 2023 12:20:04 +0100 Subject: [PATCH 001/255] pkt/spao: add support for authenticated SCMP error messages (#4255) Add support for SPAO headers to slayers and the router data plane. This will be used to authenticate SCMP error messages. Currently, the DRKey provider is not implemented in the router. Furthermore, the SCMP error messages are not yet authenticated on the receiver side. --- pkg/slayers/pkt_auth.go | 19 +- pkg/slayers/pkt_auth_test.go | 4 +- pkg/spao/BUILD.bazel | 44 +++ pkg/spao/doc.go | 21 ++ pkg/spao/export_test.go | 19 + pkg/spao/mac.go | 201 ++++++++++ pkg/spao/mac_test.go | 342 ++++++++++++++++++ pkg/spao/timestamp.go | 40 ++ router/BUILD.bazel | 2 + router/dataplane.go | 212 ++++++++++- tools/braccept/cases/BUILD.bazel | 3 + tools/braccept/cases/scmp.go | 87 +++++ tools/braccept/cases/scmp_dest_unreachable.go | 19 +- tools/braccept/cases/scmp_expired_hop.go | 237 +++++++++--- tools/braccept/cases/scmp_invalid_hop.go | 42 ++- tools/braccept/cases/scmp_invalid_ia.go | 78 ++-- tools/braccept/cases/scmp_invalid_mac.go | 38 +- tools/braccept/cases/scmp_invalid_pkt.go | 62 ++-- .../cases/scmp_invalid_segment_change.go | 76 ++-- .../scmp_invalid_segment_change_local.go | 57 +-- tools/braccept/cases/scmp_traceroute.go | 214 ++++++++++- tools/braccept/cases/scmp_unknown_hop.go | 38 +- tools/braccept/main.go | 10 +- 23 files changed, 1610 insertions(+), 255 deletions(-) create mode 100644 pkg/spao/BUILD.bazel create mode 100644 pkg/spao/doc.go create mode 100644 pkg/spao/export_test.go create mode 100644 pkg/spao/mac.go create mode 100644 pkg/spao/mac_test.go create mode 100644 pkg/spao/timestamp.go create mode 100644 tools/braccept/cases/scmp.go diff --git a/pkg/slayers/pkt_auth.go b/pkg/slayers/pkt_auth.go index 9358f4e5a..eb3db8115 100644 --- a/pkg/slayers/pkt_auth.go +++ b/pkg/slayers/pkt_auth.go @@ -13,7 +13,7 @@ // limitations under the License. // This file includes the SPAO header implementation as specified -// in https://scion.docs.anapaya.net/en/latest/protocols/authenticator-option.html +// in https://docs.scion.org/en/latest/protocols/authenticator-option.html // The Authenticator option format is as follows: // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -57,11 +57,14 @@ const ( PacketAuthEarlier ) -// MinPacketAuthDataLen is the minimum size of the SPAO OptData. -// The SPAO header contains the following fixed-length fields: -// SPI (4 Bytes), Algorithm (1 Byte), Timestamp (3 Bytes), -// RSV (1 Byte) and Sequence Number (3 Bytes). -const MinPacketAuthDataLen = 12 +const ( + // PacketAuthOptionMetadataLen is the size of the SPAO Metadata and + // corresponds the minimum size of the SPAO OptData. + // The SPAO header contains the following fixed-length fields: + // SPI (4 Bytes), Algorithm (1 Byte), Timestamp (3 Bytes), + // RSV (1 Byte) and Sequence Number (3 Bytes). + PacketAuthOptionMetadataLen = 12 +) // PacketAuthSPI (Security Parameter Index) is the identifier for the key // used for the packet authentication option. DRKey values are in the @@ -169,7 +172,7 @@ func ParsePacketAuthOption(o *EndToEndOption) (PacketAuthOption, error) { return PacketAuthOption{}, serrors.New("wrong option type", "expected", OptTypeAuthenticator, "actual", o.OptType) } - if len(o.OptData) < MinPacketAuthDataLen { + if len(o.OptData) < PacketAuthOptionMetadataLen { return PacketAuthOption{}, serrors.New("buffer too short", "expected at least", 12, "actual", len(o.OptData)) } @@ -191,7 +194,7 @@ func (o PacketAuthOption) Reset( o.OptType = OptTypeAuthenticator - n := MinPacketAuthDataLen + len(p.Auth) + n := PacketAuthOptionMetadataLen + len(p.Auth) if n <= cap(o.OptData) { o.OptData = o.OptData[:n] } else { diff --git a/pkg/slayers/pkt_auth_test.go b/pkg/slayers/pkt_auth_test.go index 98e36fef4..1b102192e 100644 --- a/pkg/slayers/pkt_auth_test.go +++ b/pkg/slayers/pkt_auth_test.go @@ -27,8 +27,8 @@ import ( var ( algo = slayers.PacketAuthSHA1_AES_CBC - ts = binary.LittleEndian.Uint32([]byte{1, 2, 3, 0}) - sn = binary.LittleEndian.Uint32([]byte{4, 5, 6, 0}) + ts = uint32(0x030201) + sn = uint32(0x060504) optAuthMAC = []byte("16byte_mac_foooo") ) diff --git a/pkg/spao/BUILD.bazel b/pkg/spao/BUILD.bazel new file mode 100644 index 000000000..c7ce25057 --- /dev/null +++ b/pkg/spao/BUILD.bazel @@ -0,0 +1,44 @@ +load("//tools/lint:go.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "mac.go", + "timestamp.go", + ], + importpath = "github.com/scionproto/scion/pkg/spao", + visibility = ["//visibility:public"], + deps = [ + "//pkg/private/serrors:go_default_library", + "//pkg/private/util:go_default_library", + "//pkg/slayers:go_default_library", + "//pkg/slayers/path:go_default_library", + "//pkg/slayers/path/epic:go_default_library", + "//pkg/slayers/path/onehop:go_default_library", + "//pkg/slayers/path/scion:go_default_library", + "@com_github_dchest_cmac//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "export_test.go", + "mac_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//pkg/addr:go_default_library", + "//pkg/drkey:go_default_library", + "//pkg/private/xtest:go_default_library", + "//pkg/slayers:go_default_library", + "//pkg/slayers/path:go_default_library", + "//pkg/slayers/path/epic:go_default_library", + "//pkg/slayers/path/onehop:go_default_library", + "//pkg/slayers/path/scion:go_default_library", + "@com_github_dchest_cmac//:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", + ], +) diff --git a/pkg/spao/doc.go b/pkg/spao/doc.go new file mode 100644 index 000000000..a56700067 --- /dev/null +++ b/pkg/spao/doc.go @@ -0,0 +1,21 @@ +// Copyright 2022 ETH Zurich +// +// 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 spao implements the logic needed to provide support for the +// SCION Packet Authenticator Option defined on: +// https://docs.scion.org/en/latest/protocols/authenticator-option.html +// +// It provides support for the MAC and the timestamp computations +// used when utilizing the SPAO header. +package spao diff --git a/pkg/spao/export_test.go b/pkg/spao/export_test.go new file mode 100644 index 000000000..c49080f6e --- /dev/null +++ b/pkg/spao/export_test.go @@ -0,0 +1,19 @@ +// Copyright 2022 ETH Zurich +// +// 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 spao + +var ( + SerializeAuthenticatedData = serializeAuthenticatedData +) diff --git a/pkg/spao/mac.go b/pkg/spao/mac.go new file mode 100644 index 000000000..7daf09c41 --- /dev/null +++ b/pkg/spao/mac.go @@ -0,0 +1,201 @@ +// Copyright 2022 ETH Zurich +// +// 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 spao + +import ( + "crypto/aes" + "encoding/binary" + "fmt" + "hash" + + "github.com/dchest/cmac" + + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/pkg/slayers/path/epic" + "github.com/scionproto/scion/pkg/slayers/path/onehop" + "github.com/scionproto/scion/pkg/slayers/path/scion" +) + +const ( + // FixAuthDataInputLen is the unvariable fields length for the + // authenticated data. It consists of the Authenticator Option Metadata + // length and the SCION Common Header without the second row. + fixAuthDataInputLen = slayers.PacketAuthOptionMetadataLen + + slayers.CmnHdrLen - slayers.LineLen + // MACBufferSize sets an upperBound to the authenticated data + // length (excluding the payload). This is: + // 1. Authenticator Option Meta + // 2. SCION Common Header + // 3. SCION Address Header + // 4. Path + // (see https://docs.scion.org/en/latest/protocols/authenticator-option.html#authenticated-data) + // We round this up to 12B (authenticator option meta) + 1020B (max SCION header length) + // To adapt to any possible path types. + MACBufferSize = 1032 +) + +type MACInput struct { + Key []byte + Header slayers.PacketAuthOption + ScionLayer *slayers.SCION + PldType slayers.L4ProtocolType + Pld []byte +} + +// ComputeAuthCMAC computes the authenticator tag for the AES-CMAC algorithm. +// The key should correspond to the SPI defined in opt.SPI. +// The SCION layer, payload type and payload define the input to the MAC, as defined in +// https://docs.scion.org/en/latest/protocols/authenticator-option.html#authenticated-data. +// +// The aux buffer is used as a temporary buffer for the MAC computation. +// It must be at least MACBufferSize long. +// The resulting MAC is written to outBuffer (appending, if necessary), +// and returned as a slice of length 16. +func ComputeAuthCMAC( + input MACInput, + auxBuffer []byte, + outBuffer []byte, +) ([]byte, error) { + + cmac, err := initCMAC(input.Key) + if err != nil { + return nil, err + } + inputLen, err := serializeAuthenticatedData( + auxBuffer, + input.ScionLayer, + input.Header, + input.PldType, + input.Pld, + ) + if err != nil { + return nil, err + } + cmac.Write(auxBuffer[:inputLen]) + cmac.Write(input.Pld) + return cmac.Sum(outBuffer[:0]), nil +} + +func initCMAC(key []byte) (hash.Hash, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, serrors.WrapStr("unable to initialize AES cipher", err) + } + mac, err := cmac.New(block) + if err != nil { + return nil, serrors.WrapStr("unable to initialize Mac", err) + } + return mac, nil +} + +func serializeAuthenticatedData( + buf []byte, + s *slayers.SCION, + opt slayers.PacketAuthOption, + pldType slayers.L4ProtocolType, + pld []byte, +) (int, error) { + + _ = buf[MACBufferSize-1] + + buf[0] = byte(slayers.CmnHdrLen + s.AddrHdrLen() + s.Path.Len()) + buf[1] = byte(pldType) + binary.BigEndian.PutUint16(buf[2:], uint16(len(pld))) + buf[4] = byte(opt.Algorithm()) + buf[5] = byte(opt.Timestamp() >> 16) + buf[6] = byte(opt.Timestamp() >> 8) + buf[7] = byte(opt.Timestamp()) + buf[8] = byte(0) + buf[9] = byte(opt.SequenceNumber() >> 16) + buf[10] = byte(opt.SequenceNumber() >> 8) + buf[11] = byte(opt.SequenceNumber()) + firstHdrLine := uint32(s.Version&0xF)<<28 | uint32(s.TrafficClass&0x3f)<<20 | s.FlowID&0xFFFFF + binary.BigEndian.PutUint32(buf[12:], firstHdrLine) + buf[16] = byte(s.PathType) + buf[17] = byte(s.DstAddrType&0x7)<<4 | byte(s.SrcAddrType&0x7) + binary.BigEndian.PutUint16(buf[18:], 0) + offset := fixAuthDataInputLen + + if !opt.SPI().IsDRKey() { + binary.BigEndian.PutUint64(buf[offset:], uint64(s.DstIA)) + binary.BigEndian.PutUint64(buf[offset+8:], uint64(s.SrcIA)) + offset += 16 + } + if !opt.SPI().IsDRKey() || + (opt.SPI().Type() == slayers.PacketAuthASHost && + opt.SPI().Direction() == slayers.PacketAuthReceiverSide) { + offset += copy(buf[offset:], s.RawDstAddr) + } + if !opt.SPI().IsDRKey() || + (opt.SPI().Type() == slayers.PacketAuthASHost && + opt.SPI().Direction() == slayers.PacketAuthSenderSide) { + offset += copy(buf[offset:], s.RawSrcAddr) + } + err := zeroOutMutablePath(s.Path, buf[offset:]) + if err != nil { + return 0, err + } + offset += s.Path.Len() + return offset, nil +} + +func zeroOutMutablePath(orig path.Path, buf []byte) error { + err := orig.SerializeTo(buf) + if err != nil { + return serrors.WrapStr("serializing path for resetting fields", err) + } + switch p := orig.(type) { + case *scion.Raw: + zeroOutWithBase(p.Base, buf) + return nil + case *scion.Decoded: + zeroOutWithBase(p.Base, buf) + return nil + case *epic.Path: + zeroOutWithBase(p.ScionPath.Base, buf[epic.MetadataLen:]) + return nil + case *onehop.Path: + // Zero out IF.SegID + binary.BigEndian.PutUint16(buf[2:], 0) + // Zero out HF.Flags&&Alerts + buf[8] = 0 + // Zero out second HF + copy(buf[20:], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) + return nil + default: + return serrors.New(fmt.Sprintf("unknown path type %T", orig)) + } +} + +func zeroOutWithBase(base scion.Base, buf []byte) { + // Zero out CurrInf && CurrHF + offset := 0 + buf[offset] = 0 + offset += 4 + for i := 0; i < base.NumINF; i++ { + // Zero out IF.SegID + binary.BigEndian.PutUint16(buf[offset+2:], 0) + offset += 8 + } + for i := 0; i < base.NumINF; i++ { + for j := 0; j < int(base.PathMeta.SegLen[i]); j++ { + // Zero out HF.Flags&&Alerts + buf[offset] = 0 + offset += 12 + } + } +} diff --git a/pkg/spao/mac_test.go b/pkg/spao/mac_test.go new file mode 100644 index 000000000..a54a891dc --- /dev/null +++ b/pkg/spao/mac_test.go @@ -0,0 +1,342 @@ +// Copyright 2022 ETH Zurich +// +// 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 spao_test + +import ( + "crypto/aes" + "encoding/binary" + "net" + "testing" + + "github.com/dchest/cmac" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/private/xtest" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/pkg/slayers/path/epic" + "github.com/scionproto/scion/pkg/slayers/path/onehop" + "github.com/scionproto/scion/pkg/slayers/path/scion" + "github.com/scionproto/scion/pkg/spao" +) + +func TestComputeAuthMac(t *testing.T) { + srcIA := xtest.MustParseIA("1-ff00:0:111") + dstIA := xtest.MustParseIA("1-ff00:0:112") + authKey := drkey.Key{0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7} + sn := uint32(0x060504) + ts := uint32(0x030201) + fooPayload := []byte("some payload") + decodedPath := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrINF: 0x03, + CurrHF: 0x3b, + SegLen: [3]byte{1, 1, 1}, + }, + NumINF: 3, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + { + ConsDir: false, + SegID: 0xf001, + Timestamp: ts, + }, + { + ConsDir: false, + SegID: 0xf002, + Timestamp: ts, + }, + { + ConsDir: true, + SegID: 0xf003, + Timestamp: ts, + }, + }, + HopFields: []path.HopField{ + { + EgressRouterAlert: true, + ExpTime: 63, + ConsIngress: 0, + ConsEgress: 1, + Mac: [path.MacLen]byte{1, 2, 3, 4, 5, 6}, + }, + { + IngressRouterAlert: true, + EgressRouterAlert: true, + ExpTime: 63, + ConsIngress: 2, + ConsEgress: 3, + Mac: [path.MacLen]byte{1, 2, 3, 4, 5, 6}, + }, + { + IngressRouterAlert: true, + ExpTime: 63, + ConsIngress: 4, + ConsEgress: 0, + Mac: [path.MacLen]byte{1, 2, 3, 4, 5, 6}, + }, + }, + } + + rawPath := make([]byte, decodedPath.Len()) + err := decodedPath.SerializeTo(rawPath) + require.NoError(t, err) + + testCases := map[string]struct { + optionParameter slayers.PacketAuthOptionParams + scionL slayers.SCION + pld []byte + rawMACInput []byte + assertErr assert.ErrorAssertionFunc + }{ + "decoded": { + optionParameter: slayers.PacketAuthOptionParams{ + SPI: slayers.PacketAuthSPI(0x1), + Algorithm: slayers.PacketAuthCMAC, + Timestamp: 0x3e8, + SequenceNumber: sn, + Auth: make([]byte, 16), + }, + scionL: slayers.SCION{ + FlowID: binary.BigEndian.Uint32([]byte{0x00, 0x00, 0x12, 0x34}), + TrafficClass: 0xff, + NextHdr: slayers.End2EndClass, + SrcIA: srcIA, + DstIA: dstIA, + SrcAddrType: slayers.T16Ip, + RawSrcAddr: net.ParseIP("2001:cafe::1").To16(), + DstAddrType: slayers.T4Svc, + RawDstAddr: addr.HostSVCFromString("CS").Pack(), + Path: decodedPath, + PathType: decodedPath.Type(), + }, + pld: fooPayload, + rawMACInput: append([]byte{ + // 1. Authenticator Option Metadata + 0x70, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length + 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp + 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number + // 2. SCION Common Header + 0x3, 0xf0, 0x12, 0x34, // Version | QoS | FlowID + 0x1, 0x43, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV + // 3. SCION Address Header + 0x20, 0x01, 0xca, 0xfe, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, + // Zeroed-out path + 0x0, 0x0, 0x10, 0x41, // Path Meta Header (CurrINF, CurrHF = 0) + 0x0, 0x0, 0x0, 0x0, // Info[0] (SegID = 0) + 0x0, 0x3, 0x2, 0x1, + 0x0, 0x0, 0x0, 0x0, // Info[1] (SegID = 0) + 0x0, 0x3, 0x2, 0x1, + 0x1, 0x0, 0x0, 0x0, // Info[2] (SegID = 0) + 0x0, 0x3, 0x2, 0x1, + 0x0, 0x3f, 0x0, 0x0, // Hop[0] (ConsIngress/Egress Alert = 0) + 0x0, 0x1, 0x1, 0x2, + 0x3, 0x4, 0x5, 0x6, + 0x0, 0x3f, 0x0, 0x2, // Hop[1] (ConsIngress/Egress Alert = 0) + 0x0, 0x3, 0x1, 0x2, + 0x3, 0x4, 0x5, 0x6, + 0x0, 0x3f, 0x0, 0x4, // Hop[2] (ConsIngress/Egress Router Alert = 0) + 0x0, 0x0, 0x1, 0x2, + 0x3, 0x4, 0x5, 0x6, + }, fooPayload...), + assertErr: assert.NoError, + }, + "one hop": { + optionParameter: slayers.PacketAuthOptionParams{ + SPI: slayers.PacketAuthSPI(0x1), + Algorithm: slayers.PacketAuthCMAC, + Timestamp: 0x3e8, + SequenceNumber: sn, + Auth: make([]byte, 16), + }, + scionL: slayers.SCION{ + HdrLen: 255, + FlowID: binary.BigEndian.Uint32([]byte{0x00, 0x00, 0x12, 0x34}), + TrafficClass: 0xff, + NextHdr: slayers.End2EndClass, + SrcIA: srcIA, + DstIA: dstIA, + SrcAddrType: slayers.T4Ip, + RawSrcAddr: net.IPv4(192, 0, 0, 2).To4(), + DstAddrType: slayers.T4Ip, + RawDstAddr: net.IPv4(192, 0, 0, 1).To4(), + Path: &onehop.Path{ + Info: path.InfoField{ + ConsDir: false, + SegID: 0xf001, + Timestamp: ts, + }, + + FirstHop: path.HopField{ + EgressRouterAlert: true, + ExpTime: 63, + ConsIngress: 0, + ConsEgress: 1, + Mac: [path.MacLen]byte{1, 2, 3, 4, 5, 6}, + }, + SecondHop: path.HopField{ + IngressRouterAlert: true, + ExpTime: 63, + ConsIngress: 2, + ConsEgress: 3, + Mac: [path.MacLen]byte{1, 2, 3, 4, 5, 6}, + }, + }, + PathType: onehop.PathType, + }, + pld: fooPayload, + rawMACInput: append([]byte{ + // 1. Authenticator Option Metadata + 0x44, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length + 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp + 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number + // 2. SCION Common Header + 0x3, 0xf0, 0x12, 0x34, // Version | QoS | FlowID + 0x2, 0x0, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV + // 3. SCION Address Header + 0xc0, 0x0, 0x0, 0x2, + // Zeroed-out path + 0x0, 0x0, 0x0, 0x0, // Info (SegID = 0) + 0x0, 0x3, 0x2, 0x1, + 0x0, 0x3f, 0x0, 0x0, // Hop[0] (ConsIngress/Egress Alert = 0) + 0x0, 0x1, 0x1, 0x2, + 0x3, 0x4, 0x5, 0x6, + 0x0, 0x0, 0x0, 0x0, // Hop[1] (zeroed-out) + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + }, fooPayload...), + assertErr: assert.NoError, + }, + "epic": { + optionParameter: slayers.PacketAuthOptionParams{ + SPI: slayers.PacketAuthSPI(2 ^ 21 - 1), + Algorithm: slayers.PacketAuthCMAC, + Timestamp: 0x3e8, + SequenceNumber: sn, + Auth: make([]byte, 16), + }, + scionL: slayers.SCION{ + HdrLen: 255, + FlowID: binary.BigEndian.Uint32([]byte{0x00, 0x00, 0x12, 0x34}), + TrafficClass: 0xff, + NextHdr: slayers.End2EndClass, + SrcIA: srcIA, + DstIA: dstIA, + SrcAddrType: slayers.T4Ip, + RawSrcAddr: net.IPv4(192, 0, 0, 2).To4(), + DstAddrType: slayers.T4Ip, + RawDstAddr: net.IPv4(192, 0, 0, 1).To4(), + PathType: epic.PathType, + Path: &epic.Path{ + PktID: epic.PktID{ + Timestamp: 1, + Counter: 0x02000003, + }, + PHVF: []byte{1, 2, 3, 4}, + LHVF: []byte{5, 6, 7, 8}, + ScionPath: &scion.Raw{ + Base: decodedPath.Base, + Raw: rawPath, + }, + }, + }, + pld: fooPayload, + rawMACInput: append([]byte{ + + // 1. Authenticator Option Metadata + 0x74, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length + 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp + 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number + // 2. SCION Common Header + 0x3, 0xf0, 0x12, 0x34, // Version | QoS | FlowID + 0x3, 0x0, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV + // 3. SCION Address Header + 0xc0, 0x0, 0x0, 0x2, + // Epic-HP header + 0x0, 0x0, 0x0, 0x1, 0x2, 0x0, 0x0, 0x3, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, + // Zeroed-out path + 0x0, 0x0, 0x10, 0x41, // Path Meta Header (CurrINF, CurrHF = 0) + 0x0, 0x0, 0x0, 0x0, // Info[0] (SegID = 0) + 0x0, 0x3, 0x2, 0x1, + 0x0, 0x0, 0x0, 0x0, // Info[1] (SegID = 0) + 0x0, 0x3, 0x2, 0x1, + 0x1, 0x0, 0x0, 0x0, // Info[2] (SegID = 0) + 0x0, 0x3, 0x2, 0x1, + 0x0, 0x3f, 0x0, 0x0, // Hop[0] (ConsIngress/Egress Alert = 0) + 0x0, 0x1, 0x1, 0x2, + 0x3, 0x4, 0x5, 0x6, + 0x0, 0x3f, 0x0, 0x2, // Hop[1] (ConsIngress/Egress Alert = 0) + 0x0, 0x3, 0x1, 0x2, + 0x3, 0x4, 0x5, 0x6, + 0x0, 0x3f, 0x0, 0x4, // Hop[2] (ConsIngress/Egress Router Alert = 0) + 0x0, 0x0, 0x1, 0x2, + 0x3, 0x4, 0x5, 0x6, + }, fooPayload...), + assertErr: assert.NoError, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + + optAuth, err := slayers.NewPacketAuthOption(tc.optionParameter) + assert.NoError(t, err) + + buf := make([]byte, spao.MACBufferSize) + inpLen, _ := spao.SerializeAuthenticatedData( + buf, + &tc.scionL, + optAuth, + slayers.L4SCMP, + tc.pld, + ) + require.Equal(t, tc.rawMACInput, append(buf[:inpLen], fooPayload...)) + + mac, err := spao.ComputeAuthCMAC( + spao.MACInput{ + authKey[:], + optAuth, + &tc.scionL, + slayers.L4SCMP, + tc.pld, + }, + make([]byte, spao.MACBufferSize), + optAuth.Authenticator(), + ) + tc.assertErr(t, err) + if err != nil { + return + } + + block, err := aes.NewCipher(authKey[:]) + require.NoError(t, err) + macFunc, err := cmac.New(block) + require.NoError(t, err) + + macFunc.Write(tc.rawMACInput) + expectedMac := macFunc.Sum(nil) + assert.Equal(t, expectedMac, mac) + }) + } +} diff --git a/pkg/spao/timestamp.go b/pkg/spao/timestamp.go new file mode 100644 index 000000000..0298340e2 --- /dev/null +++ b/pkg/spao/timestamp.go @@ -0,0 +1,40 @@ +// Copyright 2022 ETH Zurich +// +// 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 spao + +import ( + "time" + + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/private/util" +) + +// RelativeTimestamp computes the relative timestamp (spaoTS) where: +// now = ts+spaoTS⋅𝑞, (where q := 6 ms and ts = info[0].Timestamp, i.e., +// the timestamp field in the first InfoField). +func RelativeTimestamp(ts uint32, now time.Time) (uint32, error) { + timestamp := now.Sub(util.SecsToTime(ts)).Milliseconds() / 6 + if timestamp >= (1 << 24) { + return 0, serrors.New("relative timestamp is bigger than 2^24-1") + } + return uint32(timestamp), nil +} + +// Time computes the time instant (then) where: +// then = ts + spaoTS⋅𝑞, (where q := 6 ms and ts = info[0].Timestamp, i.e., +// the timestamp field in the first InfoField). +func Time(ts uint32, spaoTS uint32) time.Time { + return util.SecsToTime(ts).Add(time.Millisecond * time.Duration(spaoTS) * 6) +} diff --git a/router/BUILD.bazel b/router/BUILD.bazel index 8768d2894..57fae70cd 100644 --- a/router/BUILD.bazel +++ b/router/BUILD.bazel @@ -12,6 +12,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/addr:go_default_library", + "//pkg/drkey:go_default_library", "//pkg/experimental/epic:go_default_library", "//pkg/log:go_default_library", "//pkg/private/common:go_default_library", @@ -24,6 +25,7 @@ go_library( "//pkg/slayers/path/epic:go_default_library", "//pkg/slayers/path/onehop:go_default_library", "//pkg/slayers/path/scion:go_default_library", + "//pkg/spao:go_default_library", "//private/topology:go_default_library", "//private/underlay/conn:go_default_library", "//router/bfd:go_default_library", diff --git a/router/dataplane.go b/router/dataplane.go index 8cdd6e8bf..6365b9784 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -34,6 +34,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/drkey" libepic "github.com/scionproto/scion/pkg/experimental/epic" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/serrors" @@ -45,6 +46,7 @@ import ( "github.com/scionproto/scion/pkg/slayers/path/epic" "github.com/scionproto/scion/pkg/slayers/path/onehop" "github.com/scionproto/scion/pkg/slayers/path/scion" + "github.com/scionproto/scion/pkg/spao" "github.com/scionproto/scion/private/topology" "github.com/scionproto/scion/private/underlay/conn" underlayconn "github.com/scionproto/scion/private/underlay/conn" @@ -65,6 +67,10 @@ const ( // hopFieldDefaultExpTime is the default validity of the hop field // and 63 is equivalent to 6h. hopFieldDefaultExpTime = 63 + + // e2eAuthHdrLen is the length in bytes of added information when a SCMP packet + // needs to be authenticated: 16B (e2e.option.Len()) + 16B (CMAC_tag.Len()). + e2eAuthHdrLen = 32 ) type bfdSession interface { @@ -120,8 +126,15 @@ var ( noBFDSessionFound = serrors.New("no BFD sessions was found") noBFDSessionConfigured = serrors.New("no BFD sessions have been configured") errBFDDisabled = serrors.New("BFD is disabled") + // zeroBuffer will be used to reset the Authenticator option in the + // scionPacketProcessor.OptAuth + zeroBuffer = make([]byte, 16) ) +type drkeyProvider interface { + GetAuthKey(validTime time.Time, dstIA addr.IA, dstAddr net.Addr) (drkey.Key, error) +} + type scmpError struct { TypeCode slayers.SCMPTypeCode Cause error @@ -563,7 +576,12 @@ func newPacketProcessor(d *DataPlane, ingressID uint16) *scionPacketProcessor { macBuffers: macBuffers{ scionInput: make([]byte, path.MACBufferSize), epicInput: make([]byte, libepic.MACBufferSize), + drkeyInput: make([]byte, spao.MACBufferSize), }, + // TODO(JordiSubira): Replace this with a useful implementation. + drkeyProvider: &fakeProvider{}, + optAuth: slayers.PacketAuthOption{EndToEndOption: new(slayers.EndToEndOption)}, + validAuthBuf: make([]byte, 16), } p.scionLayer.RecyclePaths() return p @@ -581,6 +599,10 @@ func (p *scionPacketProcessor) reset() error { } p.mac.Reset() p.cachedMac = nil + // Reset hbh layer + p.hbhLayer = slayers.HopByHopExtnSkipper{} + // Reset e2e layer + p.e2eLayer = slayers.EndToEndExtnSkipper{} return nil } @@ -772,12 +794,21 @@ type scionPacketProcessor struct { // bfdLayer is reusable buffer for parsing BFD messages bfdLayer layers.BFD + // optAuth is a reusable Packet Authenticator Option + optAuth slayers.PacketAuthOption + // validAuthBuf is a reusable buffer for the authentication tag + // to be used in the hasValidAuth() method. + validAuthBuf []byte + + // DRKey key derivation for SCMP authentication + drkeyProvider drkeyProvider } // macBuffers are preallocated buffers for the in- and outputs of MAC functions. type macBuffers struct { scionInput []byte epicInput []byte + drkeyInput []byte } func (p *scionPacketProcessor) packSCMP( @@ -1602,18 +1633,22 @@ func (p *scionPacketProcessor) prepareSCMP( scmpH := slayers.SCMP{TypeCode: typeCode} scmpH.SetNetworkLayerForChecksum(&scionL) - if err := p.buffer.Clear(); err != nil { - return nil, err - } + // Error messages must be authenticated. + // Traceroute are OPTIONALLY authenticated ONLY IF the request + // was authenticated. + // TODO(JordiSubira): Reuse the key computed in p.hasValidAuth + // if SCMPTypeTracerouteReply to create the response. + needsAuth := cause != nil || + (scmpH.TypeCode.Type() == slayers.SCMPTypeTracerouteReply && + p.hasValidAuth()) - sopts := gopacket.SerializeOptions{ - ComputeChecksums: true, - FixLengths: true, - } - scmpLayers := []gopacket.SerializableLayer{&scionL, &scmpH, scmpP} + var quote []byte if cause != nil { // add quote for errors. hdrLen := slayers.CmnHdrLen + scionL.AddrHdrLen() + scionL.Path.Len() + if needsAuth { + hdrLen += e2eAuthHdrLen + } switch scmpH.TypeCode.Type() { case slayers.SCMPTypeExternalInterfaceDown: hdrLen += 20 @@ -1622,19 +1657,162 @@ func (p *scionPacketProcessor) prepareSCMP( default: hdrLen += 8 } - quote := p.rawPkt + quote = p.rawPkt maxQuoteLen := slayers.MaxSCMPPacketLen - hdrLen if len(quote) > maxQuoteLen { quote = quote[:maxQuoteLen] } - scmpLayers = append(scmpLayers, gopacket.Payload(quote)) } + + if err := p.buffer.Clear(); err != nil { + return nil, err + } + sopts := gopacket.SerializeOptions{ + ComputeChecksums: true, + FixLengths: true, + } + // First write the SCMP message only without the SCION header(s) to get a buffer that we + // can (re-)use as input in the MAC computation. // XXX(matzf) could we use iovec gather to avoid copying quote? - err = gopacket.SerializeLayers(p.buffer, sopts, scmpLayers...) + err = gopacket.SerializeLayers(p.buffer, sopts, &scmpH, scmpP, gopacket.Payload(quote)) if err != nil { return nil, serrors.Wrap(cannotRoute, err, "details", "serializing SCMP message") } - return p.buffer.Bytes(), scmpError{TypeCode: typeCode, Cause: cause} + + if needsAuth { + var e2e slayers.EndToEndExtn + scionL.NextHdr = slayers.End2EndClass + + now := time.Now() + // srcA == scionL.DstAddr + key, err := p.drkeyProvider.GetAuthKey(now, scionL.DstIA, srcA) + if err != nil { + return nil, serrors.Wrap(cannotRoute, err, "details", "retrieving DRKey") + } + if err := p.resetSPAOMetadata(now); err != nil { + return nil, serrors.Wrap(cannotRoute, err, "details", "resetting SPAO header") + } + + e2e.Options = []*slayers.EndToEndOption{p.optAuth.EndToEndOption} + e2e.NextHdr = slayers.L4SCMP + _, err = spao.ComputeAuthCMAC( + spao.MACInput{ + Key: key[:], + Header: p.optAuth, + ScionLayer: &scionL, + PldType: slayers.L4SCMP, + Pld: p.buffer.Bytes(), + }, + p.macBuffers.drkeyInput, + p.optAuth.Authenticator(), + ) + if err != nil { + return nil, serrors.Wrap(cannotRoute, err, "details", "computing CMAC") + } + if err := e2e.SerializeTo(p.buffer, sopts); err != nil { + return nil, serrors.Wrap(cannotRoute, err, "details", "serializing SCION E2E headers") + } + } else { + scionL.NextHdr = slayers.L4SCMP + } + if err := scionL.SerializeTo(p.buffer, sopts); err != nil { + return nil, serrors.Wrap(cannotRoute, err, "details", "serializing SCION header") + } + + return p.buffer.Bytes(), scmpError{TypeCode: scmpH.TypeCode, Cause: cause} +} + +func (p *scionPacketProcessor) resetSPAOMetadata(now time.Time) error { + // For creating SCMP responses we use sender side. + dir := slayers.PacketAuthSenderSide + // TODO(JordiSubira): We assume the later epoch at the moment. + // If the authentication stems from an authenticated request, we want to use + // the same key as the one used by the request sender. + epoch := slayers.PacketAuthLater + drkeyType := slayers.PacketAuthASHost + + spi, err := slayers.MakePacketAuthSPIDRKey(uint16(drkey.SCMP), drkeyType, dir, epoch) + if err != nil { + return err + } + + firstInfo, err := p.path.GetInfoField(0) + if err != nil { + return err + } + + timestamp, err := spao.RelativeTimestamp(firstInfo.Timestamp, now) + if err != nil { + return err + } + + // XXX(JordiSubira): Assume that send rate is low so that combination + // with timestamp is always unique + sn := uint32(0) + return p.optAuth.Reset(slayers.PacketAuthOptionParams{ + SPI: spi, + Algorithm: slayers.PacketAuthCMAC, + Timestamp: timestamp, + SequenceNumber: sn, + Auth: zeroBuffer, + }) +} + +func (p *scionPacketProcessor) hasValidAuth() bool { + // Check if e2eLayer was parsed for this packet + if !p.lastLayer.CanDecode().Contains(slayers.LayerTypeEndToEndExtn) { + return false + } + // Parse incoming authField + e2eLayer := &slayers.EndToEndExtn{} + if err := e2eLayer.DecodeFromBytes( + p.e2eLayer.Contents, + gopacket.NilDecodeFeedback, + ); err != nil { + return false + } + e2eOption, err := e2eLayer.FindOption(slayers.OptTypeAuthenticator) + if err != nil { + return false + } + authOption, err := slayers.ParsePacketAuthOption(e2eOption) + if err != nil { + return false + } + // Computing authField + firstInfo, err := p.path.GetInfoField(0) + if err != nil { + return false + } + then := spao.Time(firstInfo.Timestamp, authOption.Timestamp()) + srcAddr, err := p.scionLayer.SrcAddr() + if err != nil { + return false + } + // the sender should have used the receiver side key, i.e., K_{localIA-remoteIA:remoteHost} + // where remoteIA == p.scionLayer.SrcIA and remoteHost == srcAddr + // (for the incoming packet). + key, err := p.drkeyProvider.GetAuthKey(then, p.scionLayer.SrcIA, srcAddr) + if err != nil { + return false + } + _, err = spao.ComputeAuthCMAC( + spao.MACInput{ + Key: key[:], + Header: authOption, + ScionLayer: &p.scionLayer, + PldType: slayers.L4SCMP, + Pld: p.lastLayer.LayerPayload(), + }, + p.macBuffers.drkeyInput, + p.validAuthBuf, + ) + if err != nil { + return false + } + + // compare incoming authField with computed authentication tag + return subtle.ConstantTimeCompare(authOption.Authenticator(), p.validAuthBuf) != 0 } // decodeLayers implements roughly the functionality of @@ -1722,3 +1900,13 @@ func serviceMetricLabels(localIA addr.IA, svc addr.HostSVC) prometheus.Labels { "service": svc.BaseString(), } } + +type fakeProvider struct{} + +func (p *fakeProvider) GetAuthKey( + _ time.Time, + _ addr.IA, + _ net.Addr, +) (drkey.Key, error) { + return drkey.Key{}, nil +} diff --git a/tools/braccept/cases/BUILD.bazel b/tools/braccept/cases/BUILD.bazel index 77968257d..c25dd33e9 100644 --- a/tools/braccept/cases/BUILD.bazel +++ b/tools/braccept/cases/BUILD.bazel @@ -13,6 +13,7 @@ go_library( "onehop.go", "parent_to_child.go", "parent_to_internal.go", + "scmp.go", "scmp_dest_unreachable.go", "scmp_expired_hop.go", "scmp_invalid_hop.go", @@ -29,6 +30,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/addr:go_default_library", + "//pkg/drkey:go_default_library", "//pkg/private/util:go_default_library", "//pkg/private/xtest:go_default_library", "//pkg/slayers:go_default_library", @@ -36,6 +38,7 @@ go_library( "//pkg/slayers/path/empty:go_default_library", "//pkg/slayers/path/onehop:go_default_library", "//pkg/slayers/path/scion:go_default_library", + "//pkg/spao:go_default_library", "//tools/braccept/runner:go_default_library", "@com_github_google_gopacket//:go_default_library", "@com_github_google_gopacket//layers:go_default_library", diff --git a/tools/braccept/cases/scmp.go b/tools/braccept/cases/scmp.go new file mode 100644 index 000000000..28f6d8c6f --- /dev/null +++ b/tools/braccept/cases/scmp.go @@ -0,0 +1,87 @@ +// Copyright 2022 ETH Zurich +// +// 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 cases + +import ( + "github.com/google/gopacket" + + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/tools/braccept/runner" +) + +func scmpNormalizePacket(pkt gopacket.Packet) { + // Apply all the standard normalizations. + runner.DefaultNormalizePacket(pkt) + normalizePacketAuthOption(pkt) +} + +// normalizePacketAuthOption zeros out the impredictable fields for the runner +// case, i.e. the timestamp, the sequence number and the authenticator which +// includes the previous fields among others. +func normalizePacketAuthOption(pkt gopacket.Packet) { + e2e := pkt.Layer(slayers.LayerTypeEndToEndExtn) + if e2e == nil { + return + } + opt, err := e2e.(*slayers.EndToEndExtn).FindOption(slayers.OptTypeAuthenticator) + if err != nil { + return + } + optAuth, err := slayers.ParsePacketAuthOption(opt) + if err != nil { + return + } + spi := optAuth.SPI() + alg := optAuth.Algorithm() + auth := []byte{0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0} + _ = optAuth.Reset(slayers.PacketAuthOptionParams{ + SPI: spi, + Algorithm: alg, + Timestamp: uint32(0), + SequenceNumber: uint32(0), + Auth: auth, + }) +} + +func normalizedSCMPPacketAuthEndToEndExtn() *slayers.EndToEndExtn { + spi, err := slayers.MakePacketAuthSPIDRKey( + uint16(drkey.SCMP), + slayers.PacketAuthASHost, + slayers.PacketAuthSenderSide, + slayers.PacketAuthLater, + ) + if err != nil { + panic(err) + } + packAuthOpt, err := slayers.NewPacketAuthOption(slayers.PacketAuthOptionParams{ + SPI: spi, + Algorithm: slayers.PacketAuthCMAC, + Timestamp: uint32(0), + SequenceNumber: uint32(0), + Auth: make([]byte, 16), + }) + if err != nil { + panic(err) + } + return &slayers.EndToEndExtn{ + Options: []*slayers.EndToEndOption{ + packAuthOpt.EndToEndOption, + }, + } +} diff --git a/tools/braccept/cases/scmp_dest_unreachable.go b/tools/braccept/cases/scmp_dest_unreachable.go index cc4fc7f5a..23009632e 100644 --- a/tools/braccept/cases/scmp_dest_unreachable.go +++ b/tools/braccept/cases/scmp_dest_unreachable.go @@ -148,7 +148,9 @@ func SCMPDestinationUnreachable(artifactsDir string, mac hash.Hash) runner.Case if err := sp.IncPath(); err != nil { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeDestinationUnreachable, slayers.SCMPCodeNoRoute), @@ -160,17 +162,18 @@ func SCMPDestinationUnreachable(artifactsDir string, mac hash.Hash) runner.Case quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPDestinationUnreachable", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPDestinationUnreachable"), + Name: "SCMPDestinationUnreachable", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPDestinationUnreachable"), + NormalizePacket: scmpNormalizePacket, } } diff --git a/tools/braccept/cases/scmp_expired_hop.go b/tools/braccept/cases/scmp_expired_hop.go index 6ef772849..371ff440c 100644 --- a/tools/braccept/cases/scmp_expired_hop.go +++ b/tools/braccept/cases/scmp_expired_hop.go @@ -118,6 +118,115 @@ func SCMPExpiredHop(artifactsDir string, mac hash.Hash) runner.Case { scionudp.DstPort = 40222 scionudp.SetNetworkLayerForChecksum(scionL) + payload := []byte("actualpayloadbytes") + // Prepare input packet + input := gopacket.NewSerializeBuffer() + if err := gopacket.SerializeLayers(input, options, + ethernet, ip, udp, scionL, scionudp, gopacket.Payload(payload), + ); err != nil { + panic(err) + } + + // Prepare want packet + + return runner.Case{ + Name: "SCMPExpiredHop", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: nil, + StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHop"), + NormalizePacket: scmpNormalizePacket, + } +} + +// SCMPExpiredHopMessageBack tests a packet with an expired hop field. The relative timestamp +// can be encoded in the SPAO header and sent back to the src. +func SCMPExpiredHopMessageBack(artifactsDir string, mac hash.Hash) runner.Case { + options := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + + // Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4 + ethernet := &layers.Ethernet{ + SrcMAC: net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0xbe, 0xef}, + DstMAC: net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0x00, 0x13}, + EthernetType: layers.EthernetTypeIPv4, + } + // IP4: Src=192.168.13.3 Dst=192.168.13.2 NextHdr=UDP Flags=DF + ip := &layers.IPv4{ + Version: 4, + IHL: 5, + TTL: 64, + SrcIP: net.IP{192, 168, 13, 3}, + DstIP: net.IP{192, 168, 13, 2}, + Protocol: layers.IPProtocolUDP, + Flags: layers.IPv4DontFragment, + } + // UDP: Src=40000 Dst=50000 + udp := &layers.UDP{ + SrcPort: layers.UDPPort(40000), + DstPort: layers.UDPPort(50000), + } + _ = udp.SetNetworkLayerForChecksum(ip) + + // pkt0.ParsePacket(` + // SCION: NextHdr=UDP CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=IPv4 + // ADDR: SrcIA=1-ff00:0:3 Src=174.16.3.1 DstIA=1-ff00:0:4 Dst=174.16.4.1 + // IF_1: ISD=1 Hops=3 Flags=ConsDir + // HF_1: ConsIngress=0 ConsEgress=311 + // HF_2: ConsIngress=131 ConsEgress=141 + // HF_3: ConsIngress=411 ConsEgress=0 + // UDP_1: Src=40111 Dst=40222 + // `) + sp := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 1, + SegLen: [3]uint8{3, 0, 0}, + }, + NumINF: 1, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + { + SegID: 0x111, + ConsDir: true, + Timestamp: util.TimeToSecs(time.Now().Add(-6 * time.Minute)), + }, + }, + HopFields: []path.HopField{ + {ConsIngress: 0, ConsEgress: 311}, + {ConsIngress: 131, ConsEgress: 141}, + {ConsIngress: 411, ConsEgress: 0}, + }, + } + sp.HopFields[1].Mac = path.MAC(mac, sp.InfoFields[0], sp.HopFields[1], nil) + + scionL := &slayers.SCION{ + Version: 0, + TrafficClass: 0xb8, + FlowID: 0xdead, + NextHdr: slayers.L4UDP, + PathType: scion.PathType, + SrcIA: xtest.MustParseIA("1-ff00:0:3"), + DstIA: xtest.MustParseIA("1-ff00:0:4"), + Path: sp, + } + srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1").To4()} + if err := scionL.SetSrcAddr(srcA); err != nil { + panic(err) + } + if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + panic(err) + } + + scionudp := &slayers.UDP{} + scionudp.SrcPort = 40111 + scionudp.DstPort = 40222 + scionudp.SetNetworkLayerForChecksum(scionL) + payload := []byte("actualpayloadbytes") pointer := slayers.CmnHdrLen + scionL.AddrHdrLen() + (4 + 8*sp.NumINF + 12*int(sp.PathMeta.CurrHF)) @@ -159,7 +268,9 @@ func SCMPExpiredHop(artifactsDir string, mac hash.Hash) runner.Case { if err := sp.IncPath(); err != nil { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodePathExpired), @@ -173,24 +284,26 @@ func SCMPExpiredHop(artifactsDir string, mac hash.Hash) runner.Case { quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPExpiredHop", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHop"), + Name: "SCMPExpiredHopMessageBack", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopMessageBack"), + NormalizePacket: scmpNormalizePacket, } } -// SCMPExpiredHopAfterXover tests a packet with an expired hop field after an -// x-over. -func SCMPExpiredHopAfterXover(artifactsDir string, mac hash.Hash) runner.Case { +// SCMPExpiredHopAfterXoverMessageBack tests a packet with an expired hop field after an +// x-over. The relative timestamp can be encoded +// in the SPAO header and sent back to the src. +func SCMPExpiredHopAfterXoverMessageBack(artifactsDir string, mac hash.Hash) runner.Case { options := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, @@ -242,7 +355,7 @@ func SCMPExpiredHopAfterXover(artifactsDir string, mac hash.Hash) runner.Case { { SegID: 0x222, ConsDir: false, - Timestamp: util.TimeToSecs(time.Now().AddDate(0, 0, -5)), + Timestamp: util.TimeToSecs(time.Now().Add(-6 * time.Minute)), }, }, HopFields: []path.HopField{ @@ -336,7 +449,9 @@ func SCMPExpiredHopAfterXover(artifactsDir string, mac hash.Hash) runner.Case { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodePathExpired), @@ -348,24 +463,26 @@ func SCMPExpiredHopAfterXover(artifactsDir string, mac hash.Hash) runner.Case { } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPExpiredHopAfterXover", - WriteTo: "veth_151_host", - ReadFrom: "veth_151_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXover"), + Name: "SCMPExpiredHopAfterXoverMessageBack", + WriteTo: "veth_151_host", + ReadFrom: "veth_151_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverMessageBack"), + NormalizePacket: scmpNormalizePacket, } } -// SCMPExpiredHopAfterXoverConsDir tests a packet with an expired hop field after an -// x-over. -func SCMPExpiredHopAfterXoverConsDir(artifactsDir string, mac hash.Hash) runner.Case { +// SCMPExpiredHopAfterXoverConsDirMessageBack tests a packet with an expired hop field after an +// x-over. The relative timestamp can be encoded +// in the SPAO header and sent back to the src. +func SCMPExpiredHopAfterXoverConsDirMessageBack(artifactsDir string, mac hash.Hash) runner.Case { options := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, @@ -414,7 +531,7 @@ func SCMPExpiredHopAfterXoverConsDir(artifactsDir string, mac hash.Hash) runner. { SegID: 0x222, ConsDir: true, - Timestamp: util.TimeToSecs(time.Now().AddDate(0, 0, -5)), + Timestamp: util.TimeToSecs(time.Now().Add(-6 * time.Minute)), }, }, HopFields: []path.HopField{ @@ -508,7 +625,9 @@ func SCMPExpiredHopAfterXoverConsDir(artifactsDir string, mac hash.Hash) runner. panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodePathExpired), @@ -520,25 +639,27 @@ func SCMPExpiredHopAfterXoverConsDir(artifactsDir string, mac hash.Hash) runner. } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPExpiredHopAfterXoverConsDir", - WriteTo: "veth_151_host", - ReadFrom: "veth_151_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverConsDir"), + Name: "SCMPExpiredHopAfterXoverConsDirMessageBack", + WriteTo: "veth_151_host", + ReadFrom: "veth_151_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverConsDirMessageBack"), + NormalizePacket: scmpNormalizePacket, } } // SCMPExpiredHopAfterXoverInternal tests a packet with an expired hop // field after an x-over received from an internal router. The expired path -// segment is against construction direction. -func SCMPExpiredHopAfterXoverInternal(artifactsDir string, mac hash.Hash) runner.Case { +// segment is against construction direction. The relative timestamp can be encoded +// in the SPAO header and sent back to the src. +func SCMPExpiredHopAfterXoverInternalMessageBack(artifactsDir string, mac hash.Hash) runner.Case { options := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, @@ -590,7 +711,7 @@ func SCMPExpiredHopAfterXoverInternal(artifactsDir string, mac hash.Hash) runner { SegID: 0x222, ConsDir: false, - Timestamp: util.TimeToSecs(time.Now().AddDate(0, 0, -5)), + Timestamp: util.TimeToSecs(time.Now().Add(-6 * time.Minute)), }, }, HopFields: []path.HopField{ @@ -674,7 +795,9 @@ func SCMPExpiredHopAfterXoverInternal(artifactsDir string, mac hash.Hash) runner panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodePathExpired), @@ -686,25 +809,31 @@ func SCMPExpiredHopAfterXoverInternal(artifactsDir string, mac hash.Hash) runner } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPExpiredHopAfterXoverInternal", - WriteTo: "veth_int_host", - ReadFrom: "veth_int_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverInternal"), + Name: "SCMPExpiredHopAfterXoverInternalMessageBack", + WriteTo: "veth_int_host", + ReadFrom: "veth_int_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverInternalMessageBack"), + NormalizePacket: scmpNormalizePacket, } } -// SCMPExpiredHopAfterXoverInternalConsDir tests a packet with an expired hop +// SCMPExpiredHopAfterXoverInternalConsDirMessageBack tests a packet with an expired hop // field after an x-over received from an internal router. The expired path -// segment is in construction direction. -func SCMPExpiredHopAfterXoverInternalConsDir(artifactsDir string, mac hash.Hash) runner.Case { +// segment is in construction direction. The expired path +// segment is against construction direction. The relative timestamp can be encoded +// in the SPAO header and sent back to the src. +func SCMPExpiredHopAfterXoverInternalConsDirMessageBack( + artifactsDir string, + mac hash.Hash, +) runner.Case { options := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, @@ -753,7 +882,7 @@ func SCMPExpiredHopAfterXoverInternalConsDir(artifactsDir string, mac hash.Hash) { SegID: 0x222, ConsDir: true, - Timestamp: util.TimeToSecs(time.Now().AddDate(0, 0, -5)), + Timestamp: util.TimeToSecs(time.Now().Add(-6 * time.Minute)), }, }, HopFields: []path.HopField{ @@ -837,7 +966,9 @@ func SCMPExpiredHopAfterXoverInternalConsDir(artifactsDir string, mac hash.Hash) panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodePathExpired), @@ -849,17 +980,21 @@ func SCMPExpiredHopAfterXoverInternalConsDir(artifactsDir string, mac hash.Hash) } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPExpiredHopAfterXoverInternalConsDir", + Name: "SCMPExpiredHopAfterXoverInternalConsDirMessageBack", WriteTo: "veth_int_host", ReadFrom: "veth_int_host", Input: input.Bytes(), Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverInternalConsDir"), + StoreDir: filepath.Join( + artifactsDir, + "SCMPExpiredHopAfterXoverInternalConsDirMessageBack", + ), + NormalizePacket: scmpNormalizePacket, } } diff --git a/tools/braccept/cases/scmp_invalid_hop.go b/tools/braccept/cases/scmp_invalid_hop.go index f2637e0fa..36b9a9339 100644 --- a/tools/braccept/cases/scmp_invalid_hop.go +++ b/tools/braccept/cases/scmp_invalid_hop.go @@ -160,32 +160,35 @@ func SCMPInvalidHopParentToParent(artifactsDir string, mac hash.Hash) runner.Cas panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode( slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidPath, ), } - scmpH.SetNetworkLayerForChecksum(scionL) + scmpH.SetNetworkLayerForChecksum(scionL) scmpP := &slayers.SCMPParameterProblem{ Pointer: uint16(pointer), } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPInvalidHopParentToParent", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPInvalidHopParentToParent"), + Name: "SCMPInvalidHopParentToParent", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPInvalidHopParentToParent"), + NormalizePacket: scmpNormalizePacket, } } @@ -318,31 +321,34 @@ func SCMPInvalidHopChildToChild(artifactsDir string, mac hash.Hash) runner.Case panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode( slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidPath, ), } - scmpH.SetNetworkLayerForChecksum(scionL) + scmpH.SetNetworkLayerForChecksum(scionL) scmpP := &slayers.SCMPParameterProblem{ Pointer: uint16(pointer), } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPInvalidHopChildToChild", - WriteTo: "veth_141_host", - ReadFrom: "veth_141_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPInvalidHopChildToChild"), + Name: "SCMPInvalidHopChildToChild", + WriteTo: "veth_141_host", + ReadFrom: "veth_141_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPInvalidHopChildToChild"), + NormalizePacket: scmpNormalizePacket, } } diff --git a/tools/braccept/cases/scmp_invalid_ia.go b/tools/braccept/cases/scmp_invalid_ia.go index a163ba0b7..d5115bf67 100644 --- a/tools/braccept/cases/scmp_invalid_ia.go +++ b/tools/braccept/cases/scmp_invalid_ia.go @@ -145,7 +145,10 @@ func SCMPInvalidSrcIAInternalHostToChild(artifactsDir string, mac hash.Hash) run if err != nil { panic(err) } - scionL.NextHdr = slayers.L4SCMP + + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidSourceAddress), @@ -159,18 +162,19 @@ func SCMPInvalidSrcIAInternalHostToChild(artifactsDir string, mac hash.Hash) run quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPInvalidSrcIAInternalHostToChild", - WriteTo: "veth_int_host", - ReadFrom: "veth_int_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPInvalidSrcIAInternalHostToChild"), + Name: "SCMPInvalidSrcIAInternalHostToChild", + WriteTo: "veth_int_host", + ReadFrom: "veth_int_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPInvalidSrcIAInternalHostToChild"), + NormalizePacket: scmpNormalizePacket, } } @@ -288,7 +292,10 @@ func SCMPInvalidDstIAInternalHostToChild(artifactsDir string, mac hash.Hash) run if err != nil { panic(err) } - scionL.NextHdr = slayers.L4SCMP + + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidDestinationAddress), @@ -302,18 +309,19 @@ func SCMPInvalidDstIAInternalHostToChild(artifactsDir string, mac hash.Hash) run quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPInvalidDstIAInternalHostToChild", - WriteTo: "veth_int_host", - ReadFrom: "veth_int_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPInvalidDstIAInternalHostToChild"), + Name: "SCMPInvalidDstIAInternalHostToChild", + WriteTo: "veth_int_host", + ReadFrom: "veth_int_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPInvalidDstIAInternalHostToChild"), + NormalizePacket: scmpNormalizePacket, } } @@ -441,7 +449,9 @@ func SCMPInvalidSrcIAChildToParent(artifactsDir string, mac hash.Hash) runner.Ca panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidSourceAddress), @@ -455,18 +465,19 @@ func SCMPInvalidSrcIAChildToParent(artifactsDir string, mac hash.Hash) runner.Ca quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPInvalidSrcIAChildToParent", - WriteTo: "veth_141_host", - ReadFrom: "veth_141_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPInvalidSrcIAChildToParent"), + Name: "SCMPInvalidSrcIAChildToParent", + WriteTo: "veth_141_host", + ReadFrom: "veth_141_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPInvalidSrcIAChildToParent"), + NormalizePacket: scmpNormalizePacket, } } @@ -594,7 +605,9 @@ func SCMPInvalidDstIAChildToParent(artifactsDir string, mac hash.Hash) runner.Ca panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidDestinationAddress), @@ -608,17 +621,18 @@ func SCMPInvalidDstIAChildToParent(artifactsDir string, mac hash.Hash) runner.Ca quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPInvalidDstIAChildToParent", - WriteTo: "veth_141_host", - ReadFrom: "veth_141_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPInvalidDstIAChildToParent"), + Name: "SCMPInvalidDstIAChildToParent", + WriteTo: "veth_141_host", + ReadFrom: "veth_141_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPInvalidDstIAChildToParent"), + NormalizePacket: scmpNormalizePacket, } } diff --git a/tools/braccept/cases/scmp_invalid_mac.go b/tools/braccept/cases/scmp_invalid_mac.go index c43b1c17c..42d7334e9 100644 --- a/tools/braccept/cases/scmp_invalid_mac.go +++ b/tools/braccept/cases/scmp_invalid_mac.go @@ -157,7 +157,9 @@ func SCMPBadMAC(artifactsDir string, mac hash.Hash) runner.Case { if err := sp.IncPath(); err != nil { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidHopFieldMAC), @@ -171,18 +173,19 @@ func SCMPBadMAC(artifactsDir string, mac hash.Hash) runner.Case { quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPBadMAC", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPBadMAC"), + Name: "SCMPBadMAC", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPBadMAC"), + NormalizePacket: scmpNormalizePacket, } } @@ -307,7 +310,9 @@ func SCMPBadMACInternal(artifactsDir string, mac hash.Hash) runner.Case { panic(err) } sp = p.(*scion.Decoded) - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidHopFieldMAC), @@ -321,17 +326,18 @@ func SCMPBadMACInternal(artifactsDir string, mac hash.Hash) runner.Case { quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPBadMACInternal", - WriteTo: "veth_int_host", - ReadFrom: "veth_int_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPBadMACInternal"), + Name: "SCMPBadMACInternal", + WriteTo: "veth_int_host", + ReadFrom: "veth_int_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPBadMACInternal"), + NormalizePacket: scmpNormalizePacket, } } diff --git a/tools/braccept/cases/scmp_invalid_pkt.go b/tools/braccept/cases/scmp_invalid_pkt.go index 6e6491782..ec2c76d0d 100644 --- a/tools/braccept/cases/scmp_invalid_pkt.go +++ b/tools/braccept/cases/scmp_invalid_pkt.go @@ -151,7 +151,9 @@ func SCMPBadPktLen(artifactsDir string, mac hash.Hash) runner.Case { if err := sp.IncPath(); err != nil { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidPacketSize), @@ -165,18 +167,19 @@ func SCMPBadPktLen(artifactsDir string, mac hash.Hash) runner.Case { quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPBadPktLen", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPBadPktLen"), + Name: "SCMPBadPktLen", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPBadPktLen"), + NormalizePacket: scmpNormalizePacket, } } @@ -306,7 +309,9 @@ func SCMPQuoteCut(artifactsDir string, mac hash.Hash) runner.Case { if err := sp.IncPath(); err != nil { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidPacketSize), @@ -318,23 +323,25 @@ func SCMPQuoteCut(artifactsDir string, mac hash.Hash) runner.Case { // Skip Ethernet + IPv4 + UDP quoteStart := 14 + 20 + 8 - // headerLen is the length of the SCION header plus the SCMP header (8). - headerLen := slayers.CmnHdrLen + scionL.AddrHdrLen() + scionL.Path.Len() + 8 + // headerLen is the length of the SCION header, plus the e2e.option len + // plus the SCMP header (8). + headerLen := slayers.CmnHdrLen + scionL.AddrHdrLen() + scionL.Path.Len() + 32 + 8 quoteEnd := quoteStart + slayers.MaxSCMPPacketLen - headerLen quote := input.Bytes()[quoteStart:quoteEnd] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPQuoteCut", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPQuoteCut"), + Name: "SCMPQuoteCut", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPQuoteCut"), + NormalizePacket: scmpNormalizePacket, } } @@ -408,7 +415,9 @@ func NoSCMPReplyForSCMPError(artifactsDir string, mac hash.Hash) runner.Case { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidPacketSize), @@ -422,7 +431,7 @@ func NoSCMPReplyForSCMPError(artifactsDir string, mac hash.Hash) runner.Case { // do a serialization run to fix lengths if err := gopacket.SerializeLayers(gopacket.NewSerializeBuffer(), options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(payload), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(payload), ); err != nil { panic(err) } @@ -438,11 +447,12 @@ func NoSCMPReplyForSCMPError(artifactsDir string, mac hash.Hash) runner.Case { panic(err) } return runner.Case{ - Name: "NoSCMPReplyForSCMPError", - WriteTo: "veth_131_host", - ReadFrom: "no_pkt_expected", - Input: input.Bytes(), - Want: nil, - StoreDir: filepath.Join(artifactsDir, "NoSCMPReplyForSCMPError"), + Name: "NoSCMPReplyForSCMPError", + WriteTo: "veth_131_host", + ReadFrom: "no_pkt_expected", + Input: input.Bytes(), + Want: nil, + StoreDir: filepath.Join(artifactsDir, "NoSCMPReplyForSCMPError"), + NormalizePacket: scmpNormalizePacket, } } diff --git a/tools/braccept/cases/scmp_invalid_segment_change.go b/tools/braccept/cases/scmp_invalid_segment_change.go index cc0ce079f..36dd425ae 100644 --- a/tools/braccept/cases/scmp_invalid_segment_change.go +++ b/tools/braccept/cases/scmp_invalid_segment_change.go @@ -172,7 +172,9 @@ func SCMPParentToParentXover(artifactsDir string, mac hash.Hash) runner.Case { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode( slayers.SCMPTypeParameterProblem, @@ -188,18 +190,19 @@ func SCMPParentToParentXover(artifactsDir string, mac hash.Hash) runner.Case { } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPParentToParentXover", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPParentToParentXover"), + Name: "SCMPParentToParentXover", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPParentToParentXover"), + NormalizePacket: scmpNormalizePacket, } } @@ -344,7 +347,9 @@ func SCMPParentToChildXover(artifactsDir string, mac hash.Hash) runner.Case { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode( slayers.SCMPTypeParameterProblem, @@ -361,18 +366,19 @@ func SCMPParentToChildXover(artifactsDir string, mac hash.Hash) runner.Case { } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPParentToChildXover", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPParentToChildXover"), + Name: "SCMPParentToChildXover", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPParentToChildXover"), + NormalizePacket: scmpNormalizePacket, } } @@ -520,7 +526,9 @@ func SCMPChildToParentXover(artifactsDir string, mac hash.Hash) runner.Case { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode( slayers.SCMPTypeParameterProblem, @@ -536,18 +544,19 @@ func SCMPChildToParentXover(artifactsDir string, mac hash.Hash) runner.Case { } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPChildToParentXover", - WriteTo: "veth_141_host", - ReadFrom: "veth_141_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPChildToParentXover"), + Name: "SCMPChildToParentXover", + WriteTo: "veth_141_host", + ReadFrom: "veth_141_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPChildToParentXover"), + NormalizePacket: scmpNormalizePacket, } } @@ -692,7 +701,9 @@ func SCMPInternalXover(artifactsDir string, mac hash.Hash) runner.Case { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH = &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode( slayers.SCMPTypeParameterProblem, @@ -708,17 +719,18 @@ func SCMPInternalXover(artifactsDir string, mac hash.Hash) runner.Case { } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpReplyP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpReplyP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPInternalXover", - WriteTo: "veth_int_host", - ReadFrom: "veth_int_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPInternalXover"), + Name: "SCMPInternalXover", + WriteTo: "veth_int_host", + ReadFrom: "veth_int_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPInternalXover"), + NormalizePacket: scmpNormalizePacket, } } diff --git a/tools/braccept/cases/scmp_invalid_segment_change_local.go b/tools/braccept/cases/scmp_invalid_segment_change_local.go index b5d4b241b..dd019f912 100644 --- a/tools/braccept/cases/scmp_invalid_segment_change_local.go +++ b/tools/braccept/cases/scmp_invalid_segment_change_local.go @@ -172,7 +172,9 @@ func SCMPParentToParentLocalXover(artifactsDir string, mac hash.Hash) runner.Cas panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode( slayers.SCMPTypeParameterProblem, @@ -188,18 +190,19 @@ func SCMPParentToParentLocalXover(artifactsDir string, mac hash.Hash) runner.Cas } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPParentToParentLocalXover", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPParentToParentLocalXover"), + Name: "SCMPParentToParentLocalXover", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPParentToParentLocalXover"), + NormalizePacket: scmpNormalizePacket, } } @@ -344,7 +347,9 @@ func SCMPParentToChildLocalXover(artifactsDir string, mac hash.Hash) runner.Case panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode( slayers.SCMPTypeParameterProblem, @@ -361,18 +366,19 @@ func SCMPParentToChildLocalXover(artifactsDir string, mac hash.Hash) runner.Case } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPParentToChildLocalXover", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPParentToChildLocalXover"), + Name: "SCMPParentToChildLocalXover", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPParentToChildLocalXover"), + NormalizePacket: scmpNormalizePacket, } } @@ -520,7 +526,9 @@ func SCMPChildToParentLocalXover(artifactsDir string, mac hash.Hash) runner.Case panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode( slayers.SCMPTypeParameterProblem, @@ -536,17 +544,18 @@ func SCMPChildToParentLocalXover(artifactsDir string, mac hash.Hash) runner.Case } if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPChildToParentLocalXover", - WriteTo: "veth_141_host", - ReadFrom: "veth_141_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPChildToParentLocalXover"), + Name: "SCMPChildToParentLocalXover", + WriteTo: "veth_141_host", + ReadFrom: "veth_141_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPChildToParentLocalXover"), + NormalizePacket: scmpNormalizePacket, } } diff --git a/tools/braccept/cases/scmp_traceroute.go b/tools/braccept/cases/scmp_traceroute.go index 897cb780d..271358d4b 100644 --- a/tools/braccept/cases/scmp_traceroute.go +++ b/tools/braccept/cases/scmp_traceroute.go @@ -23,11 +23,13 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/pkg/slayers/path/scion" + "github.com/scionproto/scion/pkg/spao" "github.com/scionproto/scion/tools/braccept/runner" ) @@ -155,7 +157,6 @@ func SCMPTracerouteIngress(artifactsDir string, mac hash.Hash) runner.Case { Interface: 141, } - // Skip Ethernet + IPv4 + UDP if err := gopacket.SerializeLayers(want, options, ethernet, ip, udp, scionL, scmpH, scmpP, ); err != nil { @@ -172,6 +173,212 @@ func SCMPTracerouteIngress(artifactsDir string, mac hash.Hash) runner.Case { } } +// SCMPTracerouteIngressWithSPAO tests an SCMP traceroute request with alert on the +// ingress interface and a SPAO header. +func SCMPTracerouteIngressWithSPAO(artifactsDir string, mac hash.Hash) runner.Case { + options := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + ethernet := &layers.Ethernet{ + SrcMAC: net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0xbe, 0xef}, + DstMAC: net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0x00, 0x14}, + EthernetType: layers.EthernetTypeIPv4, + } + ip := &layers.IPv4{ + Version: 4, + IHL: 5, + TTL: 64, + SrcIP: net.IP{192, 168, 14, 3}, + DstIP: net.IP{192, 168, 14, 2}, + Protocol: layers.IPProtocolUDP, + Flags: layers.IPv4DontFragment, + } + udp := &layers.UDP{ + SrcPort: layers.UDPPort(40000), + DstPort: layers.UDPPort(50000), + } + _ = udp.SetNetworkLayerForChecksum(ip) + + sp := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 1, + SegLen: [3]uint8{3, 0, 0}, + }, + NumINF: 1, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + { + SegID: 0x111, + ConsDir: false, + Timestamp: util.TimeToSecs(time.Now()), + }, + }, + HopFields: []path.HopField{ + {ConsIngress: 411, ConsEgress: 0}, + {ConsIngress: 121, ConsEgress: 141, EgressRouterAlert: true}, + {ConsIngress: 0, ConsEgress: 211}, + }, + } + sp.HopFields[1].Mac = path.MAC(mac, sp.InfoFields[0], sp.HopFields[1], nil) + sp.InfoFields[0].UpdateSegID(sp.HopFields[1].Mac) + + scionL := &slayers.SCION{ + Version: 0, + TrafficClass: 0xb8, + FlowID: 0xdead, + NextHdr: slayers.End2EndClass, + HdrLen: 0x15, + PayloadLen: 0x18, + PathType: scion.PathType, + SrcIA: xtest.MustParseIA("1-ff00:0:4"), + DstIA: xtest.MustParseIA("1-ff00:0:2"), + Path: sp, + } + srcA := &net.IPAddr{IP: net.ParseIP("172.16.4.1").To4()} + if err := scionL.SetSrcAddr(srcA); err != nil { + panic(err) + } + if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.2.1").To4()}); err != nil { + panic(err) + } + + scmpH := &slayers.SCMP{ + TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeTracerouteRequest, 0), + } + scmpH.SetNetworkLayerForChecksum(scionL) + scmpP := &slayers.SCMPTraceroute{ + Identifier: 567, + Sequence: 129, + } + + e2e := &slayers.EndToEndExtn{} + optAuth, err := slayers.NewPacketAuthOption(slayers.PacketAuthOptionParams{ + Auth: make([]byte, 16), + }) + if err != nil { + panic(err) + } + e2e.Options = []*slayers.EndToEndOption{optAuth.EndToEndOption} + e2e.NextHdr = slayers.L4SCMP + e2ePayload := gopacket.NewSerializeBuffer() + err = gopacket.SerializeLayers( + e2ePayload, + gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + }, + scmpH, + scmpP, + ) + if err != nil { + panic(err) + } + _, err = spao.ComputeAuthCMAC( + spao.MACInput{ + Key: (&drkey.Key{})[:], + Header: optAuth, + ScionLayer: scionL, + PldType: slayers.L4SCMP, + Pld: e2ePayload.Bytes(), + }, + + make([]byte, spao.MACBufferSize), + optAuth.Authenticator(), + ) + if err != nil { + panic(err) + } + + // Prepare input packet + input := gopacket.NewSerializeBuffer() + if err := gopacket.SerializeLayers(input, options, + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, + ); err != nil { + panic(err) + } + + // Prepare want packet + want := gopacket.NewSerializeBuffer() + ethernet.SrcMAC, ethernet.DstMAC = ethernet.DstMAC, ethernet.SrcMAC + ip.SrcIP, ip.DstIP = ip.DstIP, ip.SrcIP + udp.SrcPort, udp.DstPort = udp.DstPort, udp.SrcPort + + scionL.DstIA = scionL.SrcIA + scionL.SrcIA = xtest.MustParseIA("1-ff00:0:1") + if err := scionL.SetDstAddr(srcA); err != nil { + panic(err) + } + intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + if err := scionL.SetSrcAddr(intlA); err != nil { + panic(err) + } + + sp.HopFields[1].EgressRouterAlert = false + p, err := sp.Reverse() + if err != nil { + panic(err) + } + sp = p.(*scion.Decoded) + if err := sp.IncPath(); err != nil { + panic(err) + } + scionL.NextHdr = slayers.End2EndClass + spi, err := slayers.MakePacketAuthSPIDRKey( + uint16(drkey.SCMP), + slayers.PacketAuthASHost, + slayers.PacketAuthSenderSide, + slayers.PacketAuthLater, + ) + if err != nil { + panic(err) + } + packAuthOpt, err := slayers.NewPacketAuthOption(slayers.PacketAuthOptionParams{ + SPI: spi, + Algorithm: slayers.PacketAuthCMAC, + Timestamp: uint32(0), + SequenceNumber: uint32(0), + Auth: make([]byte, 16), + }) + if err != nil { + panic(err) + } + e2e = &slayers.EndToEndExtn{ + Options: []*slayers.EndToEndOption{ + packAuthOpt.EndToEndOption, + }, + } + e2e.NextHdr = slayers.L4SCMP + scmpH = &slayers.SCMP{ + TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeTracerouteReply, 0), + } + scmpH.SetNetworkLayerForChecksum(scionL) + scmpP = &slayers.SCMPTraceroute{ + Identifier: scmpP.Identifier, + Sequence: scmpP.Sequence, + IA: scionL.SrcIA, + Interface: 141, + } + + if err := gopacket.SerializeLayers(want, options, + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, + ); err != nil { + panic(err) + } + + return runner.Case{ + Name: "SCMPTracerouteIngressWithSPAO", + WriteTo: "veth_141_host", + ReadFrom: "veth_141_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPTracerouteIngressWithSPAO"), + NormalizePacket: scmpNormalizePacket, + } +} + // SCMPTracerouteIngressConsDir tests an SCMP traceroute request with alert on the // ingress interface. func SCMPTracerouteIngressConsDir(artifactsDir string, mac hash.Hash) runner.Case { @@ -300,7 +507,6 @@ func SCMPTracerouteIngressConsDir(artifactsDir string, mac hash.Hash) runner.Cas Interface: 131, } - // Skip Ethernet + IPv4 + UDP if err := gopacket.SerializeLayers(want, options, ethernet, ip, udp, scionL, scmpH, scmpP, ); err != nil { @@ -441,7 +647,6 @@ func SCMPTracerouteEgress(artifactsDir string, mac hash.Hash) runner.Case { Interface: 131, } - // Skip Ethernet + IPv4 + UDP if err := gopacket.SerializeLayers(want, options, ethernet, ip, udp, scionL, scmpH, scmpP, ); err != nil { @@ -586,7 +791,6 @@ func SCMPTracerouteEgressConsDir(artifactsDir string, mac hash.Hash) runner.Case Interface: 141, } - // Skip Ethernet + IPv4 + UDP if err := gopacket.SerializeLayers(want, options, ethernet, ip, udp, scionL, scmpH, scmpP, ); err != nil { @@ -745,7 +949,6 @@ func SCMPTracerouteEgressAfterXover(artifactsDir string, mac hash.Hash) runner.C Interface: 141, } - // Skip Ethernet + IPv4 + UDP if err := gopacket.SerializeLayers(want, options, ethernet, ip, udp, scionL, scmpH, scmpP, ); err != nil { @@ -881,7 +1084,6 @@ func SCMPTracerouteInternal(artifactsDir string, mac hash.Hash) runner.Case { Interface: 141, } - // Skip Ethernet + IPv4 + UDP if err := gopacket.SerializeLayers(want, options, ethernet, ip, udp, scionL, scmpH, scmpP, ); err != nil { diff --git a/tools/braccept/cases/scmp_unknown_hop.go b/tools/braccept/cases/scmp_unknown_hop.go index aeb114c5e..af7fdf278 100644 --- a/tools/braccept/cases/scmp_unknown_hop.go +++ b/tools/braccept/cases/scmp_unknown_hop.go @@ -158,7 +158,9 @@ func SCMPUnknownHop(artifactsDir string, mac hash.Hash) runner.Case { if err := sp.IncPath(); err != nil { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeUnknownHopFieldIngress), @@ -172,18 +174,19 @@ func SCMPUnknownHop(artifactsDir string, mac hash.Hash) runner.Case { quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPUnknownHop", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPUnknownHop"), + Name: "SCMPUnknownHop", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPUnknownHop"), + NormalizePacket: scmpNormalizePacket, } } @@ -314,7 +317,9 @@ func SCMPUnknownHopEgress(artifactsDir string, mac hash.Hash) runner.Case { if err := sp.IncPath(); err != nil { panic(err) } - scionL.NextHdr = slayers.L4SCMP + scionL.NextHdr = slayers.End2EndClass + e2e := normalizedSCMPPacketAuthEndToEndExtn() + e2e.NextHdr = slayers.L4SCMP scmpH := &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeParameterProblem, slayers.SCMPCodeUnknownHopFieldEgress), @@ -326,17 +331,18 @@ func SCMPUnknownHopEgress(artifactsDir string, mac hash.Hash) runner.Case { quoteStart := 14 + 20 + 8 quote := input.Bytes()[quoteStart:] if err := gopacket.SerializeLayers(want, options, - ethernet, ip, udp, scionL, scmpH, scmpP, gopacket.Payload(quote), + ethernet, ip, udp, scionL, e2e, scmpH, scmpP, gopacket.Payload(quote), ); err != nil { panic(err) } return runner.Case{ - Name: "SCMPUnknownHopEgress", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPUnknownHopEgress"), + Name: "SCMPUnknownHopEgress", + WriteTo: "veth_131_host", + ReadFrom: "veth_131_host", + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "SCMPUnknownHopEgress"), + NormalizePacket: scmpNormalizePacket, } } diff --git a/tools/braccept/main.go b/tools/braccept/main.go index 6954ea474..9a54104d5 100644 --- a/tools/braccept/main.go +++ b/tools/braccept/main.go @@ -93,11 +93,12 @@ func realMain() int { cases.SCMPDestinationUnreachable(artifactsDir, hfMAC), cases.SCMPBadMAC(artifactsDir, hfMAC), cases.SCMPBadMACInternal(artifactsDir, hfMAC), - cases.SCMPExpiredHopAfterXover(artifactsDir, hfMAC), - cases.SCMPExpiredHopAfterXoverConsDir(artifactsDir, hfMAC), - cases.SCMPExpiredHopAfterXoverInternal(artifactsDir, hfMAC), - cases.SCMPExpiredHopAfterXoverInternalConsDir(artifactsDir, hfMAC), + cases.SCMPExpiredHopAfterXoverMessageBack(artifactsDir, hfMAC), + cases.SCMPExpiredHopAfterXoverConsDirMessageBack(artifactsDir, hfMAC), + cases.SCMPExpiredHopAfterXoverInternalMessageBack(artifactsDir, hfMAC), + cases.SCMPExpiredHopAfterXoverInternalConsDirMessageBack(artifactsDir, hfMAC), cases.SCMPExpiredHop(artifactsDir, hfMAC), + cases.SCMPExpiredHopMessageBack(artifactsDir, hfMAC), cases.SCMPChildToParentXover(artifactsDir, hfMAC), cases.SCMPParentToChildXover(artifactsDir, hfMAC), cases.SCMPParentToParentXover(artifactsDir, hfMAC), @@ -115,6 +116,7 @@ func realMain() int { cases.SCMPTracerouteEgressConsDir(artifactsDir, hfMAC), cases.SCMPTracerouteEgressAfterXover(artifactsDir, hfMAC), cases.SCMPTracerouteInternal(artifactsDir, hfMAC), + cases.SCMPTracerouteIngressWithSPAO(artifactsDir, hfMAC), cases.SCMPBadPktLen(artifactsDir, hfMAC), cases.SCMPQuoteCut(artifactsDir, hfMAC), cases.SCMPInvalidSrcIAInternalHostToChild(artifactsDir, hfMAC), From f3b508f14f8c38c9cc1c50f74195b6fba9fff16d Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Wed, 25 Jan 2023 17:02:04 +0100 Subject: [PATCH 002/255] control: use AS certs in QUIC TLS, for DRKey auth (#4268) Use AS certificates in the control plane's QUIC TLS, for the benefit of authenticating DRKey Level1 requests. In contrast to other control plane requests, the DRKey Level 1 key requests require confidentiality and authentication. For these requests, we use TLS authenticated with the CP-PKI AS certificates. Previously, we would run two separate grpc "servers" on the same QUIC socket. One server without authentication, used for most control service requests, and one with grpc authentication for the DRKey requests. In either case, the underlying connection would use the TLS from QUIC with self-signed certificates without authentication (`InsecureSkipVerify: true`). For the grpc authentication, an additional TLS session would run on top, so we'd have two nested TLS sessions. This setup simply did not work properly. The two different grpc servers competed for accepted connections on the QUIC socket and chance determined whether a request would be processed by the appropriate server. Automatic request retry has hidden the problem to some extent in early testing. Fix this by always using AS certificates in the QUIC connection directly, and never using grpc's TLS. This approach has been previously considered impractical, but a grpc-go contributor pointed us in the right direction for a clean implementation now; adding a custom implementation of the `credentials.TransportCredentials` interface allows us to pass through the TLS state of the underlying QUIC connection to grpc. Note that: - we cannot verify the certificates for all requests; this would be a circular dependency e.g. for fetching certificate chains and trcs - the client certificate is now validated directly from the DRKey grpc server logic. At this point, the TLS session has already been established and any errors result in a grpc error, not a TLS handshake error. This is unavoidable, as we can only know the method invoked after accepting the TLS session to know whether the certificates should be validated (see point above). --- control/cmd/control/BUILD.bazel | 1 - control/cmd/control/main.go | 128 +++++++++++----------------- control/drkey/grpc/drkey_service.go | 50 ++++++----- control/drkey/grpc/fetcher_test.go | 106 ++++++++++++++--------- control/trust/key_loader.go | 1 - demo/drkey/test.py | 4 - pkg/grpc/BUILD.bazel | 1 + pkg/grpc/creds.go | 74 ++++++++++++++++ pkg/grpc/dialer.go | 32 +------ pkg/snet/squic/net.go | 16 +++- private/app/appnet/BUILD.bazel | 1 + private/app/appnet/infraenv.go | 35 ++++++-- private/trust/tls_handshake.go | 44 +++++++--- 13 files changed, 301 insertions(+), 192 deletions(-) create mode 100644 pkg/grpc/creds.go diff --git a/control/cmd/control/BUILD.bazel b/control/cmd/control/BUILD.bazel index 131a78806..bdb3b6307 100644 --- a/control/cmd/control/BUILD.bazel +++ b/control/cmd/control/BUILD.bazel @@ -75,7 +75,6 @@ go_library( "@com_github_spf13_cobra//:go_default_library", "@in_gopkg_yaml_v2//:go_default_library", "@org_golang_google_grpc//:go_default_library", - "@org_golang_google_grpc//credentials:go_default_library", "@org_golang_google_grpc//health:go_default_library", "@org_golang_google_grpc//health/grpc_health_v1:go_default_library", "@org_golang_x_sync//errgroup:go_default_library", diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index 8757d1b6f..7fd058a77 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -16,7 +16,6 @@ package main import ( "context" - "crypto/tls" "encoding/json" "errors" "fmt" @@ -34,7 +33,6 @@ import ( "github.com/spf13/cobra" "golang.org/x/sync/errgroup" "google.golang.org/grpc" - "google.golang.org/grpc/credentials" "google.golang.org/grpc/health" healthpb "google.golang.org/grpc/health/grpc_health_v1" "inet.af/netaddr" @@ -167,38 +165,6 @@ func realMain(ctx context.Context) error { return err } - nc := infraenv.NetworkConfig{ - IA: topo.IA(), - Public: topo.ControlServiceAddress(globalCfg.General.ID), - ReconnectToDispatcher: globalCfg.General.ReconnectToDispatcher, - QUIC: infraenv.QUIC{ - Address: globalCfg.QUIC.Address, - }, - SVCResolver: topo, - SCMPHandler: snet.DefaultSCMPHandler{ - RevocationHandler: cs.RevocationHandler{RevCache: revCache}, - SCMPErrors: metrics.SCMPErrors, - }, - SCIONNetworkMetrics: metrics.SCIONNetworkMetrics, - SCIONPacketConnMetrics: metrics.SCIONPacketConnMetrics, - } - quicStack, err := nc.QUICStack() - if err != nil { - return serrors.WrapStr("initializing QUIC stack", err) - } - defer quicStack.RedirectCloser() - tcpStack, err := nc.TCPStack() - if err != nil { - return serrors.WrapStr("initializing TCP stack", err) - } - dialer := &libgrpc.QUICDialer{ - Rewriter: &onehop.AddressRewriter{ - Rewriter: nc.AddressRewriter(nil), - MAC: macGen(), - }, - Dialer: quicStack.Dialer, - } - trustDB, err := storage.NewTrustStorage(globalCfg.TrustDB) if err != nil { return serrors.WrapStr("initializing trust storage", err) @@ -233,6 +199,46 @@ func realMain(ctx context.Context) error { return err } + loader := trust.X509KeyPairProvider{ + IA: topo.IA(), + DB: trustDB, + KeyLoader: cstrust.LoadingRing{ + Dir: filepath.Join(globalCfg.General.ConfigDir, "crypto/as"), + }, + } + nc := infraenv.NetworkConfig{ + IA: topo.IA(), + Public: topo.ControlServiceAddress(globalCfg.General.ID), + ReconnectToDispatcher: globalCfg.General.ReconnectToDispatcher, + QUIC: infraenv.QUIC{ + Address: globalCfg.QUIC.Address, + TLSManager: trust.NewTLSCryptoManager(loader, trustDB), + }, + SVCResolver: topo, + SCMPHandler: snet.DefaultSCMPHandler{ + RevocationHandler: cs.RevocationHandler{RevCache: revCache}, + SCMPErrors: metrics.SCMPErrors, + }, + SCIONNetworkMetrics: metrics.SCIONNetworkMetrics, + SCIONPacketConnMetrics: metrics.SCIONPacketConnMetrics, + } + quicStack, err := nc.QUICStack() + if err != nil { + return serrors.WrapStr("initializing QUIC stack", err) + } + defer quicStack.RedirectCloser() + tcpStack, err := nc.TCPStack() + if err != nil { + return serrors.WrapStr("initializing TCP stack", err) + } + dialer := &libgrpc.QUICDialer{ + Rewriter: &onehop.AddressRewriter{ + Rewriter: nc.AddressRewriter(nil), + MAC: macGen(), + }, + Dialer: quicStack.InsecureDialer, + } + beaconDB, err := storage.NewBeaconStorage(globalCfg.BeaconDB, topo.IA()) if err != nil { return serrors.WrapStr("initializing beacon storage", err) @@ -300,7 +306,10 @@ func realMain(ctx context.Context) error { Router: segreq.NewRouter(fetcherCfg), } - quicServer := grpc.NewServer(libgrpc.UnaryServerInterceptor()) + quicServer := grpc.NewServer( + grpc.Creds(libgrpc.PassThroughCredentials{}), + libgrpc.UnaryServerInterceptor(), + ) tcpServer := grpc.NewServer(libgrpc.UnaryServerInterceptor()) // Register trust material related handlers. @@ -568,7 +577,6 @@ func realMain(ctx context.Context) error { // DRKey feature var drkeyEngine *drkey.ServiceEngine - var quicTLSServer *grpc.Server var epochDuration time.Duration if globalCfg.DRKey.Enabled() { epochDuration, err = loadEpochDuration() @@ -614,23 +622,10 @@ func realMain(ctx context.Context) error { }, } defer level1DB.Close() - loader := trust.X509KeyPairProvider{ - IA: topo.IA(), - DB: trustDB, - KeyLoader: cstrust.LoadingRing{ - Dir: filepath.Join(globalCfg.General.ConfigDir, "crypto/as"), - }, - } - tlsMgr := trust.NewTLSCryptoManager(loader, trustDB) drkeyFetcher := drkeygrpc.Fetcher{ - Dialer: &libgrpc.TLSQUICDialer{ - QUICDialer: dialer, - Credentials: credentials.NewTLS(&tls.Config{ - InsecureSkipVerify: true, - GetClientCertificate: tlsMgr.GetClientCertificate, - VerifyPeerCertificate: tlsMgr.VerifyServerCertificate, - VerifyConnection: tlsMgr.VerifyConnection, - }), + Dialer: &libgrpc.QUICDialer{ + Rewriter: nc.AddressRewriter(nil), + Dialer: quicStack.Dialer, }, Router: segreq.NewRouter(fetcherCfg), MaxRetries: 20, @@ -647,21 +642,12 @@ func realMain(ctx context.Context) error { PrefetchKeeper: prefetchKeeper, } drkeyService := &drkeygrpc.Server{ - LocalIA: topo.IA(), - Engine: drkeyEngine, - AllowedSVHostProto: globalCfg.DRKey.Delegation.ToAllowedSet(), - } - srvConfig := &tls.Config{ - InsecureSkipVerify: true, - GetCertificate: tlsMgr.GetCertificate, - VerifyPeerCertificate: tlsMgr.VerifyClientCertificate, - ClientAuth: tls.RequireAnyClientCert, + LocalIA: topo.IA(), + ClientCertificateVerifier: nc.QUIC.TLSManager, + Engine: drkeyEngine, + AllowedSVHostProto: globalCfg.DRKey.Delegation.ToAllowedSet(), } - quicTLSServer = grpc.NewServer( - grpc.Creds(credentials.NewTLS(srvConfig)), - libgrpc.UnaryServerInterceptor(), - ) - cppb.RegisterDRKeyInterServiceServer(quicTLSServer, drkeyService) + cppb.RegisterDRKeyInterServiceServer(quicServer, drkeyService) cppb.RegisterDRKeyIntraServiceServer(tcpServer, drkeyService) log.Info("DRKey is enabled") } else { @@ -680,16 +666,6 @@ func realMain(ctx context.Context) error { return nil }) cleanup.Add(func() error { quicServer.GracefulStop(); return nil }) - if quicTLSServer != nil { - g.Go(func() error { - defer log.HandlePanic() - if err := quicTLSServer.Serve(quicStack.Listener); err != nil { - return serrors.WrapStr("serving gRPC(TLS)/QUIC API", err) - } - return nil - }) - cleanup.Add(func() error { quicTLSServer.GracefulStop(); return nil }) - } g.Go(func() error { defer log.HandlePanic() if err := tcpServer.Serve(tcpStack); err != nil { diff --git a/control/drkey/grpc/drkey_service.go b/control/drkey/grpc/drkey_service.go index dc918b807..23ca58692 100644 --- a/control/drkey/grpc/drkey_service.go +++ b/control/drkey/grpc/drkey_service.go @@ -16,6 +16,7 @@ package grpc import ( "context" + "crypto/x509" "net" "google.golang.org/grpc/credentials" @@ -31,7 +32,6 @@ import ( "github.com/scionproto/scion/pkg/private/serrors" cppb "github.com/scionproto/scion/pkg/proto/control_plane" drkeypb "github.com/scionproto/scion/pkg/proto/drkey" - "github.com/scionproto/scion/pkg/scrypto/cppki" ) type Engine interface { @@ -47,10 +47,15 @@ type Engine interface { DeriveHostHost(ctx context.Context, meta drkey.HostHostMeta) (drkey.HostHostKey, error) } +type ClientCertificateVerifier interface { + VerifyParsedClientCertificate(chain []*x509.Certificate) (addr.IA, error) +} + // Server keeps track of the drkeys. type Server struct { - LocalIA addr.IA - Engine Engine + LocalIA addr.IA + ClientCertificateVerifier ClientCertificateVerifier + Engine Engine // AllowedSVHostProto is a set of (Host,Protocol) pairs that represents the allowed // protocols hosts can obtain secrets values. AllowedSVHostProto map[config.HostProto]struct{} @@ -66,7 +71,7 @@ func (d *Server) DRKeyLevel1( if !ok { return nil, serrors.New("cannot retrieve peer information from ctx") } - dstIA, err := extractIAFromPeer(peer) + dstIA, err := d.validateClientCertificate(peer) if err != nil { return nil, serrors.WrapStr("retrieving info from certificate", err) } @@ -231,6 +236,26 @@ func (d *Server) DRKeySecretValue( return resp, nil } +func (d *Server) validateClientCertificate(peer *peer.Peer) (addr.IA, error) { + if peer.AuthInfo == nil { + return 0, serrors.New("no auth info", "peer", peer) + } + tlsInfo, ok := peer.AuthInfo.(credentials.TLSInfo) + if !ok { + return 0, serrors.New("auth info is not of type TLS info", + "peer", peer, "auth_type", peer.AuthInfo.AuthType()) + } + chain := tlsInfo.State.PeerCertificates + if len(chain) == 0 { + return 0, serrors.New("no client certificate provided") + } + certIA, err := d.ClientCertificateVerifier.VerifyParsedClientCertificate(chain) + if err != nil { + return 0, serrors.WrapStr("invalid certificate", err) + } + return certIA, nil +} + // validateAllowedHost checks that the requester is authorized to receive a SV. func (d *Server) validateAllowedHost(protoId drkey.Protocol, peerAddr net.Addr) error { tcpAddr, ok := peerAddr.(*net.TCPAddr) @@ -350,20 +375,3 @@ func getMeta(protoId drkeypb.Protocol, ts *timestamppb.Timestamp, srcIA, DstIA: dstIA, }, nil } - -func extractIAFromPeer(peer *peer.Peer) (addr.IA, error) { - if peer.AuthInfo == nil { - return 0, serrors.New("no auth info", "peer", peer) - } - tlsInfo, ok := peer.AuthInfo.(credentials.TLSInfo) - if !ok { - return 0, serrors.New("auth info is not of type TLS info", - "peer", peer, "auth_type", peer.AuthInfo.AuthType()) - } - chain := tlsInfo.State.PeerCertificates - certIA, err := cppki.ExtractIA(chain[0].Subject) - if err != nil { - return 0, serrors.WrapStr("extracting IA from peer cert", err) - } - return certIA, nil -} diff --git a/control/drkey/grpc/fetcher_test.go b/control/drkey/grpc/fetcher_test.go index 9a8a80b96..e93db1cd5 100644 --- a/control/drkey/grpc/fetcher_test.go +++ b/control/drkey/grpc/fetcher_test.go @@ -24,6 +24,7 @@ import ( "time" "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc/credentials" @@ -44,6 +45,10 @@ import ( var _ csdrkey.Fetcher = (*dk_grpc.Fetcher)(nil) func TestLevel1KeyFetching(t *testing.T) { + // In this test, we request the Level1 key from the local AS. This never + // happens in the real system. + // This test uses grpc's TLS stack, unlike the real system, where the TLS of + // the QUIC session is used. dir := genCrypto(t) trc := xtest.LoadTRC(t, filepath.Join(dir, "trcs/ISD1-B1-S1.trc")) @@ -57,7 +62,7 @@ func TestLevel1KeyFetching(t *testing.T) { defer ctrl.Finish() lvl1db := mock_grpc.NewMockEngine(ctrl) - lvl1db.EXPECT().DeriveLevel1(gomock.Any()).Return(drkey.Level1Key{}, nil) + lvl1db.EXPECT().DeriveLevel1(gomock.Any()).AnyTimes().Return(drkey.Level1Key{}, nil) mgrdb := mock_trust.NewMockDB(ctrl) mgrdb.EXPECT().SignedTRC(gomock.Any(), gomock.Any()).AnyTimes().Return(trc, nil) @@ -66,51 +71,76 @@ func TestLevel1KeyFetching(t *testing.T) { loader.EXPECT().LoadServerKeyPair(gomock.Any()).AnyTimes().Return(&tlsCert, nil) mgr := trust.NewTLSCryptoManager(loader, mgrdb) - serverCreds := credentials.NewTLS(&tls.Config{ - InsecureSkipVerify: true, - GetCertificate: mgr.GetCertificate, - VerifyPeerCertificate: mgr.VerifyClientCertificate, - ClientAuth: tls.RequireAnyClientCert, - }) - clientCreds := credentials.NewTLS(&tls.Config{ - InsecureSkipVerify: true, - GetClientCertificate: mgr.GetClientCertificate, - VerifyPeerCertificate: mgr.VerifyServerCertificate, - VerifyConnection: mgr.VerifyConnection, - }) - - server := xtest.NewGRPCService(xtest.WithCredentials(clientCreds, serverCreds)) - cppb.RegisterDRKeyInterServiceServer(server.Server(), &dk_grpc.Server{ - Engine: lvl1db, - }) - server.Start(t) - path := mock_snet.NewMockPath(ctrl) path.EXPECT().Metadata().AnyTimes().Return(&snet.PathMetadata{ - Interfaces: []snet.PathInterface{ - {IA: xtest.MustParseIA("1-ff00:0:111"), ID: 2}, - {IA: xtest.MustParseIA("1-ff00:0:110"), ID: 1}, - }, + Interfaces: []snet.PathInterface{}, }) - path.EXPECT().Dataplane().Return(nil) - path.EXPECT().UnderlayNextHop().Return(&net.UDPAddr{}) + path.EXPECT().Dataplane().AnyTimes().Return(nil) + path.EXPECT().UnderlayNextHop().AnyTimes().Return(&net.UDPAddr{}) router := mock_snet.NewMockRouter(ctrl) - router.EXPECT().AllRoutes(gomock.Any(), gomock.Any()).Return([]snet.Path{path}, nil) - - fetcher := dk_grpc.Fetcher{ - Dialer: server, - Router: router, - MaxRetries: 10, + router.EXPECT().AllRoutes(gomock.Any(), gomock.Any()).AnyTimes().Return([]snet.Path{path}, nil) + + testCases := map[string]struct { + omitClientCert bool + assertErr assert.ErrorAssertionFunc + }{ + "ok": { + omitClientCert: false, + assertErr: assert.NoError, + }, + "no certificate": { + omitClientCert: true, + assertErr: assert.Error, + }, } - meta := drkey.Level1Meta{ - ProtoId: drkey.Generic, - Validity: time.Now(), - SrcIA: xtest.MustParseIA("1-ff00:0:111"), + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + + // TODO(matzf): change xtest library to allow specifying the client + // credentials for individual calls so that server does not need to be + // recreated here. + serverCreds := credentials.NewTLS(&tls.Config{ + InsecureSkipVerify: true, + GetCertificate: mgr.GetCertificate, + VerifyPeerCertificate: nil, // certificate verified in the service + ClientAuth: tls.RequestClientCert, + }) + + clientTLSConfig := &tls.Config{ + InsecureSkipVerify: true, + GetClientCertificate: mgr.GetClientCertificate, + VerifyPeerCertificate: mgr.VerifyServerCertificate, + VerifyConnection: mgr.VerifyConnection, + } + if tc.omitClientCert { + clientTLSConfig.GetClientCertificate = nil + } + clientCreds := credentials.NewTLS(clientTLSConfig) + + server := xtest.NewGRPCService(xtest.WithCredentials(clientCreds, serverCreds)) + cppb.RegisterDRKeyInterServiceServer(server.Server(), &dk_grpc.Server{ + Engine: lvl1db, + ClientCertificateVerifier: mgr, + }) + server.Start(t) + + fetcher := dk_grpc.Fetcher{ + Dialer: server, + Router: router, + MaxRetries: 1, + } + + meta := drkey.Level1Meta{ + ProtoId: drkey.Generic, + Validity: time.Now(), + SrcIA: xtest.MustParseIA("1-ff00:0:111"), + } + _, err = fetcher.Level1(context.Background(), meta) + tc.assertErr(t, err) + }) } - _, err = fetcher.Level1(context.Background(), meta) - require.NoError(t, err) } func genCrypto(t testing.TB) string { diff --git a/control/trust/key_loader.go b/control/trust/key_loader.go index bb0c0aff0..2812862e8 100644 --- a/control/trust/key_loader.go +++ b/control/trust/key_loader.go @@ -37,7 +37,6 @@ func (r LoadingRing) PrivateKeys(ctx context.Context) ([]crypto.Signer, error) { if err != nil { return nil, err } - log.FromCtx(ctx).Debug("available keys:", "files", files) var signers []crypto.Signer for _, file := range files { diff --git a/demo/drkey/test.py b/demo/drkey/test.py index e9acb00ce..30eab6e3e 100644 --- a/demo/drkey/test.py +++ b/demo/drkey/test.py @@ -98,10 +98,6 @@ def _run(self): print(rs) # Demonstrate obtaining key (slow) on client side - - # Show available paths that can be used to fetch key: - print(self.dc.execute("tester_%s" % self.client_isd_as.file_fmt(), - "scion", "showpaths", str(self.server_isd_as))) rc = self.dc.execute("tester_%s" % self.client_isd_as.file_fmt(), "drkey-demo", "--server-addr", server_addr, "--client-addr", client_addr) diff --git a/pkg/grpc/BUILD.bazel b/pkg/grpc/BUILD.bazel index 6f229f1c0..e93b7512b 100644 --- a/pkg/grpc/BUILD.bazel +++ b/pkg/grpc/BUILD.bazel @@ -3,6 +3,7 @@ load("//tools/lint:go.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "creds.go", "dialer.go", "interceptor.go", ], diff --git a/pkg/grpc/creds.go b/pkg/grpc/creds.go new file mode 100644 index 000000000..ef2de5ff8 --- /dev/null +++ b/pkg/grpc/creds.go @@ -0,0 +1,74 @@ +// Copyright 2021 ETH Zurich +// +// 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 grpc + +import ( + "context" + "crypto/tls" + "net" + + "google.golang.org/grpc/credentials" +) + +type ConnectionStater interface { + ConnectionState() tls.ConnectionState +} + +// PassThroughCredentials implements the grpc/credentials.TransportCredentials interface. +// It allows to pass the TLS connection state of an underlying TLS connection, +// e.g. from an underlying QUIC session, into the grpc stack. This allows accessing +// this information in the context of grpc/peer.Peer.AuthInfo. +// The handshake methods only extract the TLS state and otherwise simply +// pass-through the underlying connection object. The underlying connection +// must implement the ConnectionStater interface. +type PassThroughCredentials struct{} + +func (c PassThroughCredentials) ClientHandshake( + ctx context.Context, + authority string, + conn net.Conn, +) (net.Conn, credentials.AuthInfo, error) { + + authInfo := credentials.TLSInfo{ + State: conn.(ConnectionStater).ConnectionState(), + } + return conn, authInfo, nil +} + +func (c PassThroughCredentials) ServerHandshake( + conn net.Conn, +) (net.Conn, credentials.AuthInfo, error) { + + authInfo := credentials.TLSInfo{ + State: conn.(ConnectionStater).ConnectionState(), + } + return conn, authInfo, nil +} + +func (c PassThroughCredentials) Info() credentials.ProtocolInfo { + return credentials.ProtocolInfo{ + SecurityProtocol: "tls", // copied from grpc/credentials.tlsCreds.Info. + SecurityVersion: "1.2", // ditto + ServerName: "", // XXX(matzf) do we need to set this??? + } +} + +func (c PassThroughCredentials) Clone() credentials.TransportCredentials { + return PassThroughCredentials{} +} + +func (c PassThroughCredentials) OverrideServerName(string) error { + panic("not implemented") +} diff --git a/pkg/grpc/dialer.go b/pkg/grpc/dialer.go index 8743b5f72..952870036 100644 --- a/pkg/grpc/dialer.go +++ b/pkg/grpc/dialer.go @@ -21,7 +21,6 @@ import ( grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry" "google.golang.org/grpc" - "google.golang.org/grpc/credentials" "google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver/manual" @@ -155,36 +154,7 @@ func (d *QUICDialer) Dial(ctx context.Context, addr net.Addr) (*grpc.ClientConn, return d.Dialer.Dial(ctx, addr) } return grpc.DialContext(ctx, addr.String(), - grpc.WithInsecure(), - grpc.WithContextDialer(dialer), - UnaryClientInterceptor(), - StreamClientInterceptor(), - ) - -} - -// TLSQUICDialer dials a gRPC connection over TLS/QUIC/SCION. This dialer is meant to -// be used for secure inter AS communication. -type TLSQUICDialer struct { - *QUICDialer - Credentials credentials.TransportCredentials -} - -// Dial dials a gRPC connection over TLS/QUIC/SCION. -func (d *TLSQUICDialer) Dial(ctx context.Context, addr net.Addr) (*grpc.ClientConn, error) { - addr, _, err := d.Rewriter.RedirectToQUIC(ctx, addr) - if err != nil { - return nil, serrors.WrapStr("resolving SVC address", err) - } - if _, ok := addr.(*snet.UDPAddr); !ok { - return nil, serrors.New("wrong address type after svc resolution", - "type", common.TypeOf(addr)) - } - dialer := func(context.Context, string) (net.Conn, error) { - return d.Dialer.Dial(ctx, addr) - } - return grpc.DialContext(ctx, addr.String(), - grpc.WithTransportCredentials(d.Credentials), + grpc.WithTransportCredentials(PassThroughCredentials{}), grpc.WithContextDialer(dialer), UnaryClientInterceptor(), StreamClientInterceptor(), diff --git a/pkg/snet/squic/net.go b/pkg/snet/squic/net.go index 440d1be4b..e11ee4ab4 100644 --- a/pkg/snet/squic/net.go +++ b/pkg/snet/squic/net.go @@ -17,6 +17,7 @@ package squic import ( "context" "crypto/tls" + "errors" "fmt" mrand "math/rand" "net" @@ -312,6 +313,10 @@ func (c *acceptingConn) RemoteAddr() net.Addr { return c.session.RemoteAddr() } +func (c *acceptingConn) ConnectionState() tls.ConnectionState { + return c.session.ConnectionState().TLS.ConnectionState +} + func (c *acceptingConn) Close() error { // Prevent the stream from being accepted. c.once.Do(func() { @@ -376,9 +381,8 @@ func (d ConnDialer) Dial(ctx context.Context, dst net.Addr) (net.Conn, error) { if err == nil { break } - // Unfortunately there is no better way to check the error. - // https://github.com/lucas-clemente/quic-go/issues/2441 - if err.Error() != "SERVER_BUSY" { + var transportErr *quic.TransportError + if !errors.As(err, &transportErr) || transportErr.ErrorCode != quic.ConnectionRefused { return nil, serrors.WrapStr("dialing QUIC/SCION", err) } @@ -408,7 +412,7 @@ func (d ConnDialer) Dial(ctx context.Context, dst net.Addr) (net.Conn, error) { // with QUIC SNI. func computeAddressStr(address net.Addr) string { if v, ok := address.(*snet.UDPAddr); ok { - return fmt.Sprintf("[%s]:%d", v.Host.IP, v.Host.Port) + return fmt.Sprintf("[%s,%s]:%d", v.IA, v.Host.IP, v.Host.Port) } return address.String() } @@ -447,6 +451,10 @@ func (c *acceptedConn) RemoteAddr() net.Addr { return c.session.RemoteAddr() } +func (c *acceptedConn) ConnectionState() tls.ConnectionState { + return c.session.ConnectionState().TLS.ConnectionState +} + func (c *acceptedConn) Close() error { var errs []error if err := c.stream.Close(); err != nil { diff --git a/private/app/appnet/BUILD.bazel b/private/app/appnet/BUILD.bazel index a795a6dcd..a65d75e38 100644 --- a/private/app/appnet/BUILD.bazel +++ b/private/app/appnet/BUILD.bazel @@ -20,6 +20,7 @@ go_library( "//pkg/sock/reliable/reconnect:go_default_library", "//private/env:go_default_library", "//private/svc:go_default_library", + "//private/trust:go_default_library", "@com_github_lucas_clemente_quic_go//:go_default_library", ], ) diff --git a/private/app/appnet/infraenv.go b/private/app/appnet/infraenv.go index 765192e79..6f00a6d2b 100644 --- a/private/app/appnet/infraenv.go +++ b/private/app/appnet/infraenv.go @@ -42,12 +42,14 @@ import ( "github.com/scionproto/scion/pkg/sock/reliable/reconnect" "github.com/scionproto/scion/private/env" "github.com/scionproto/scion/private/svc" + "github.com/scionproto/scion/private/trust" ) // QUIC contains the QUIC configuration for control-plane speakers. type QUIC struct { // Address is the UDP address to start the QUIC server on. - Address string + Address string + TLSManager *trust.TLSCryptoManager } // NetworkConfig describes the networking configuration of a SCION @@ -82,6 +84,7 @@ type NetworkConfig struct { // QUICStack contains everything to run a QUIC based RPC stack. type QUICStack struct { Listener *squic.ConnListener + InsecureDialer *squic.ConnDialer Dialer *squic.ConnDialer RedirectCloser func() } @@ -105,11 +108,15 @@ func (nc *NetworkConfig) QUICStack() (*QUICStack, error) { log.Info("QUIC server conn initialized", "local_addr", server.LocalAddr()) log.Info("QUIC client conn initialized", "local_addr", client.LocalAddr()) - tlsConfig, err := GenerateTLSConfig() - if err != nil { - return nil, err + tlsMgr := nc.QUIC.TLSManager + serverTLSConfig := &tls.Config{ + InsecureSkipVerify: true, + GetCertificate: tlsMgr.GetCertificate, + ClientAuth: tls.RequestClientCert, + NextProtos: []string{"SCION"}, } - listener, err := quic.Listen(server, tlsConfig, nil) + + listener, err := quic.Listen(server, serverTLSConfig, nil) if err != nil { return nil, serrors.WrapStr("listening QUIC/SCION", err) } @@ -126,11 +133,27 @@ func (nc *NetworkConfig) QUICStack() (*QUICStack, error) { return nil, serrors.WrapStr("starting service redirection", err) } + insecureClientTLSConfig := &tls.Config{ + InsecureSkipVerify: true, + NextProtos: []string{"SCION"}, + } + clientTLSConfig := &tls.Config{ + InsecureSkipVerify: true, // ... but VerifyServerCertificate and VerifyConnection + GetClientCertificate: tlsMgr.GetClientCertificate, + VerifyPeerCertificate: tlsMgr.VerifyServerCertificate, + VerifyConnection: tlsMgr.VerifyConnection, + NextProtos: []string{"SCION"}, + } + return &QUICStack{ Listener: squic.NewConnListener(listener), + InsecureDialer: &squic.ConnDialer{ + Conn: client, + TLSConfig: insecureClientTLSConfig, + }, Dialer: &squic.ConnDialer{ Conn: client, - TLSConfig: tlsConfig, + TLSConfig: clientTLSConfig, }, RedirectCloser: cancel, }, nil diff --git a/private/trust/tls_handshake.go b/private/trust/tls_handshake.go index 464753e7a..809881e59 100644 --- a/private/trust/tls_handshake.go +++ b/private/trust/tls_handshake.go @@ -81,7 +81,7 @@ func (m *TLSCryptoManager) VerifyServerCertificate( _ [][]*x509.Certificate, ) error { - return m.verifyPeerCertificate(rawCerts, x509.ExtKeyUsageServerAuth) + return m.verifyRawPeerCertificate(rawCerts, x509.ExtKeyUsageServerAuth) } // VerifyClientCertificate verifies the certificate presented by the client @@ -91,7 +91,17 @@ func (m *TLSCryptoManager) VerifyClientCertificate( _ [][]*x509.Certificate, ) error { - return m.verifyPeerCertificate(rawCerts, x509.ExtKeyUsageClientAuth) + return m.verifyRawPeerCertificate(rawCerts, x509.ExtKeyUsageClientAuth) +} + +// VerifyParsedClientCertificate verifies the certificate presented by the +// client using the CP-PKI. +// If the certificate is valid, returns the subject IA. +func (m *TLSCryptoManager) VerifyParsedClientCertificate( + chain []*x509.Certificate, +) (addr.IA, error) { + + return m.verifyParsedPeerCertificate(chain, x509.ExtKeyUsageClientAuth) } // VerifyConnection callback is intended to be used by the client to verify @@ -101,7 +111,7 @@ func (m *TLSCryptoManager) VerifyConnection(cs tls.ConnectionState) error { serverNameIA := strings.Split(cs.ServerName, ",")[0] serverIA, err := addr.ParseIA(serverNameIA) if err != nil { - return serrors.WrapStr("extracting IA from server name", err) + return serrors.WrapStr("extracting IA from server name", err, "connState", cs) } certIA, err := cppki.ExtractIA(cs.PeerCertificates[0].Subject) if err != nil { @@ -114,9 +124,9 @@ func (m *TLSCryptoManager) VerifyConnection(cs tls.ConnectionState) error { return nil } -// verifyPeerCertificate verifies the certificate presented by the peer during TLS handshake, +// verifyRawPeerCertificate verifies the certificate presented by the peer during TLS handshake, // based on the TRC. -func (m *TLSCryptoManager) verifyPeerCertificate( +func (m *TLSCryptoManager) verifyRawPeerCertificate( rawCerts [][]byte, extKeyUsage x509.ExtKeyUsage, ) error { @@ -129,23 +139,37 @@ func (m *TLSCryptoManager) verifyPeerCertificate( } chain[i] = cert } + _, err := m.verifyParsedPeerCertificate(chain, extKeyUsage) + return err +} + +// verifyParsedPeerCertificate verifies the certificate presented by the peer during TLS handshake, +// based on the TRC. +func (m *TLSCryptoManager) verifyParsedPeerCertificate( + chain []*x509.Certificate, + extKeyUsage x509.ExtKeyUsage, +) (addr.IA, error) { + + if len(chain) == 0 { + return 0, serrors.New("no peer certificate provided") + } if err := verifyExtendedKeyUsage(chain[0], extKeyUsage); err != nil { - return err + return 0, err } ia, err := cppki.ExtractIA(chain[0].Subject) if err != nil { - return serrors.WrapStr("extracting ISD-AS from peer certificate", err) + return 0, serrors.WrapStr("extracting ISD-AS from peer certificate", err) } ctx, cancel := context.WithTimeout(context.Background(), m.Timeout) defer cancel() trcs, _, err := activeTRCs(ctx, m.DB, ia.ISD()) if err != nil { - return serrors.WrapStr("loading TRCs", err) + return 0, serrors.WrapStr("loading TRCs", err) } if err := verifyChain(chain, trcs); err != nil { - return serrors.WrapStr("verifying chains", err) + return 0, serrors.WrapStr("verifying chains", err) } - return nil + return ia, nil } func verifyChain(chain []*x509.Certificate, trcs []cppki.SignedTRC) error { From a0fcc9e754698f97d180edfb8b7a8497eacb5575 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Fri, 3 Feb 2023 14:36:16 +0100 Subject: [PATCH 003/255] doc: introduce TC Implementation (#4312) Add section on the project governance with the TC Implementation, including a list of the current members. --- doc/contribute.rst | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/doc/contribute.rst b/doc/contribute.rst index 2da62b33b..94862e791 100644 --- a/doc/contribute.rst +++ b/doc/contribute.rst @@ -79,6 +79,60 @@ remember to shoot us a question on our :ref:`Slack `. Finally, make sure that the code you write adheres to the SCION project :ref:`language-style-guides`. +.. _governance: + +Governance: TC Implementation +============================= + +The `Technical Committee (TC) Implementation `_ +of the SCION Association are the custodians of the open-source SCION +implementation projects. + +.. rubric:: People + +The current members of the TC Implementation are: + +.. |span-github| raw:: html + + + +.. |span-slack| raw:: html + + + +* Dominik Roos (|span-github| `@oncilla `_, |span-slack| @roosd) +* François Wirz (|span-github| `@FR4NK-W `_, |span-slack| @frank) +* Lukas Vogel (|span-github| `@lukedirtwalker `_, |span-slack| @luke) +* Marc Frei (|span-github| `@marcfrei `_, |span-slack| @marcfrei) +* Matthias Frei (|span-github| `@matzf `_, |span-slack| @matzf) + +.. rubric:: Responsibilities and Tasks + +The TC Implementation has the following main responsibilities, as defined in its +`charter `_: + +* Coordination with the Association Board and other bodies of the SCION + Association. In particular, coordinate with the TC Standardisation to + synchronise the evolution of the SCION standards, specifications, and their + implementation. Consult with the Advisory Board on strategic planning. +* Steering strategic direction of the open source SCION project(s); planning + projects aligned with priorities of SCION Association members and the open + source developer community. +* Deciding on cross-cutting issues such as development processes, guidelines, + tooling, etc. + +The TC may define technical teams and work groups and delegate tasks. +No technical teams or work groups are currently defined. + +Where not delegated to technical teams, the TC Implementation members +participate in the day-to-day operations to implement the +:ref:`change-proposal-process` defined below, in particular by + +* Participating in change proposal discussions and moderating discussions +* Reviewing and deciding over individual change proposals and pull requests + +.. _change-proposal-process: + Change Proposal Process ======================= From 756c8b4e0d61444f9216b586d368082e448df079 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 9 Feb 2023 16:15:39 +0100 Subject: [PATCH 004/255] pkg/private: cleanup common, util, xtest packages (#4311) The pkg/private/common, util and xtest packages have rather fuzzy scope, and have accumulated a bit of cruft and unused or outdated functionality. Clean this up a bit: * pkg/private/common: * remove unused constants * remove outdated error handling helpers and replace remaining use * remove NativeOrder and IsBigEndian: No longer needed. Native byte order is not often needed, but will eventually show up in standard library anyway (golang/go#57237). * pkg/private/util: * remove unused helper functionality * remove Checksum: only used to compute reference value in slayers test cases. Use a simpler, non-optimized implementation for this. Closes #4262. * move RunsInDocker to private/env * move ASList to tools/integration * pkg/private/xtest: * remove unused helpers * remove unused Callback and MockCallback * replace FailOnErr with require.NoError * replace AssertErrorsIs with assert.ErrorIs There are still more things to clean up in `pkg/private`, in future PRs, in particular: * `common.ErrMsg` should be integrated in `serrors` * `common.IFIDType` should be removed or renamed and moved somewhere more appropriate * Merge the remainder of `util` and `common` * Clean up `LinkType` and `RevInfo` from `pkg/private/ctrl` --- .../internal/registration/iatable_test.go | 2 +- .../internal/registration/scmp_table_test.go | 5 +- pkg/private/common/BUILD.bazel | 1 - pkg/private/common/binary.go | 36 ------- pkg/private/common/defs.go | 10 +- pkg/private/common/errors.go | 78 --------------- pkg/private/serrors/errors_test.go | 22 ++--- pkg/private/util/BUILD.bazel | 19 ---- pkg/private/util/checksum.go | 59 ------------ pkg/private/util/checksum_test.go | 62 ------------ pkg/private/util/file.go | 47 --------- pkg/private/util/map.go | 28 ------ pkg/private/util/map_test.go | 68 ------------- pkg/private/util/padding.go | 38 -------- pkg/private/util/padding_test.go | 39 -------- pkg/private/util/raw.go | 50 ---------- pkg/private/util/sync.go | 95 ------------------- pkg/private/util/yaml.go | 43 --------- pkg/private/util/yaml_test.go | 63 ------------ pkg/private/xtest/BUILD.bazel | 3 - pkg/private/xtest/convey.go | 30 ------ pkg/private/xtest/helpers.go | 37 -------- pkg/private/xtest/mock_xtest/BUILD.bazel | 18 ---- pkg/private/xtest/mock_xtest/mock.go | 46 --------- pkg/private/xtest/mocking.go | 7 -- pkg/private/xtest/waiter.go | 42 -------- pkg/scrypto/cppki/id_test.go | 3 +- pkg/scrypto/cppki/trc_test.go | 2 +- pkg/scrypto/rand.go | 3 +- pkg/slayers/BUILD.bazel | 1 - pkg/slayers/scion_test.go | 37 +++++++- pkg/slayers/slayers_test.go | 6 +- pkg/sock/reliable/BUILD.bazel | 1 + pkg/sock/reliable/errors.go | 48 +--------- pkg/sock/reliable/errors_test.go | 75 +++++++++++++++ pkg/sock/reliable/frame_test.go | 6 +- pkg/sock/reliable/reconnect/BUILD.bazel | 1 + pkg/sock/reliable/reconnect/conn_io_test.go | 3 +- pkg/sock/reliable/reconnect/reconnecter.go | 6 +- pkg/sock/reliable/registration_test.go | 8 +- private/env/BUILD.bazel | 1 + {pkg/private/util => private/env}/docker.go | 2 +- private/env/logging.go | 3 +- private/path/combinator/BUILD.bazel | 1 + private/path/combinator/combinator_test.go | 11 ++- private/path/pathpol/acl_test.go | 2 +- private/path/pathpol/policy_test.go | 4 +- private/revcache/revcachetest/BUILD.bazel | 1 + private/revcache/revcachetest/revcachetest.go | 21 ++-- private/service/BUILD.bazel | 1 - private/service/statuspages.go | 3 +- private/trust/router_test.go | 2 +- tools/end2end_integration/main.go | 11 ++- tools/integration/BUILD.bazel | 16 +++- .../util => tools/integration}/aslist.go | 2 +- .../util => tools/integration}/aslist_test.go | 10 +- tools/integration/integration.go | 11 +-- .../integration}/testdata/aslist_invalid.yml | 0 .../integration}/testdata/aslist_valid.yml | 0 59 files changed, 212 insertions(+), 1038 deletions(-) delete mode 100644 pkg/private/common/binary.go delete mode 100644 pkg/private/util/checksum.go delete mode 100644 pkg/private/util/checksum_test.go delete mode 100644 pkg/private/util/file.go delete mode 100644 pkg/private/util/map.go delete mode 100644 pkg/private/util/map_test.go delete mode 100644 pkg/private/util/padding.go delete mode 100644 pkg/private/util/padding_test.go delete mode 100644 pkg/private/util/raw.go delete mode 100644 pkg/private/util/sync.go delete mode 100644 pkg/private/util/yaml.go delete mode 100644 pkg/private/util/yaml_test.go delete mode 100644 pkg/private/xtest/convey.go delete mode 100644 pkg/private/xtest/mock_xtest/BUILD.bazel delete mode 100644 pkg/private/xtest/mock_xtest/mock.go delete mode 100644 pkg/private/xtest/waiter.go create mode 100644 pkg/sock/reliable/errors_test.go rename {pkg/private/util => private/env}/docker.go (98%) rename {pkg/private/util => tools/integration}/aslist.go (98%) rename {pkg/private/util => tools/integration}/aslist_test.go (88%) rename {pkg/private/util => tools/integration}/testdata/aslist_invalid.yml (100%) rename {pkg/private/util => tools/integration}/testdata/aslist_valid.yml (100%) diff --git a/dispatcher/internal/registration/iatable_test.go b/dispatcher/internal/registration/iatable_test.go index 7871f926a..f60db2694 100644 --- a/dispatcher/internal/registration/iatable_test.go +++ b/dispatcher/internal/registration/iatable_test.go @@ -98,7 +98,7 @@ func TestIATableRegister(t *testing.T) { t.Run("already registered ports will cause error", func(t *testing.T) { table := NewIATable(minPort, maxPort) _, err := table.Register(ia, public, nil, addr.SvcNone, value) - xtest.FailOnErr(t, err) + require.NoError(t, err) ref, err := table.Register(ia, public, nil, addr.SvcNone, value) assert.Error(t, err) assert.Nil(t, ref) diff --git a/dispatcher/internal/registration/scmp_table_test.go b/dispatcher/internal/registration/scmp_table_test.go index 5212f8a40..5c376615c 100644 --- a/dispatcher/internal/registration/scmp_table_test.go +++ b/dispatcher/internal/registration/scmp_table_test.go @@ -18,8 +18,7 @@ import ( "testing" . "github.com/smartystreets/goconvey/convey" - - "github.com/scionproto/scion/pkg/private/xtest" + "github.com/stretchr/testify/require" ) func TestSCMPEmptyTable(t *testing.T) { @@ -48,7 +47,7 @@ func TestSCMPTableWithOneItem(t *testing.T) { table := NewSCMPTable() value := "test value" err := table.Register(42, value) - xtest.FailOnErr(t, err) + require.NoError(t, err) Convey("Lookup for the id succeeds", func() { retValue, ok := table.Lookup(42) SoMsg("ok", ok, ShouldBeTrue) diff --git a/pkg/private/common/BUILD.bazel b/pkg/private/common/BUILD.bazel index 1c39bcb1c..36602cce1 100644 --- a/pkg/private/common/BUILD.bazel +++ b/pkg/private/common/BUILD.bazel @@ -3,7 +3,6 @@ load("//tools/lint:go.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "binary.go", "defs.go", "errors.go", ], diff --git a/pkg/private/common/binary.go b/pkg/private/common/binary.go deleted file mode 100644 index 17fe910ff..000000000 --- a/pkg/private/common/binary.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 ETH Zurich -// -// 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 common - -import ( - "encoding/binary" - "unsafe" -) - -var ( - NativeOrder binary.ByteOrder - IsBigEndian bool -) - -func init() { - var v uint16 = 0x11FF - if (*[2]uint8)(unsafe.Pointer(&v))[0] == 0x11 { - IsBigEndian = true - NativeOrder = binary.BigEndian - } else { - IsBigEndian = false - NativeOrder = binary.LittleEndian - } -} diff --git a/pkg/private/common/defs.go b/pkg/private/common/defs.go index ee8794072..62d0f068b 100644 --- a/pkg/private/common/defs.go +++ b/pkg/private/common/defs.go @@ -22,10 +22,8 @@ import ( ) const ( - // LineLen is the number of bytes that all SCION headers are padded to a multiple of. - LineLen = 8 - MinMTU = 1280 - MaxMTU = (1 << 16) - 1 + MinMTU = 1280 + MaxMTU = (1 << 16) - 1 // SupportedMTU is the MTU supported by dispatcher/snet and router. // Smaller than MaxMTU to avoid excessive overallocation for packet buffers. // It's chosen as a common ethernet jumbo frame size minus IP/UDP headers. @@ -34,10 +32,6 @@ const ( TimeFmtSecs = "2006-01-02 15:04:05-0700" ) -const ( - CPService = "Control Plane Service" -) - // IFIDType is the type for interface IDs. // // Deprecated: with version 2 of the SCION header, there is no interface ID type anymore. diff --git a/pkg/private/common/errors.go b/pkg/private/common/errors.go index 98d310dc5..7743cbe12 100644 --- a/pkg/private/common/errors.go +++ b/pkg/private/common/errors.go @@ -15,37 +15,6 @@ package common -import ( - "strings" -) - -// ErrorMsger allows extracting the message from an error. This means a caller -// can determine the type of error by comparing the returned message with a -// const error string. E.g.: -// -// if GetErrorMsg(err) == addr.ErrorBadHostAddrType { -// // Handle bad host addr error -// } -type ErrorMsger interface { - error - GetMsg() string -} - -// ErrorNester allows recursing into nested errors. -type ErrorNester interface { - error - TopError() string // should not include the nested error - GetErr() error -} - -// GetNestedError returns the nested error, if any. Returns nil otherwise. -func GetNestedError(e error) error { - if n, _ := e.(ErrorNester); n != nil { - return n.GetErr() - } - return nil -} - // ErrMsg should be used for error string constants. The constant can then be // used for Is checking in the calling code. type ErrMsg string @@ -53,50 +22,3 @@ type ErrMsg string func (e ErrMsg) Error() string { return string(e) } - -// FmtError formats e for logging. It walks through all nested errors, putting each on a new line, -// and indenting multi-line errors. -func FmtError(e error) string { - var s, ns []string - for { - ns, e = innerFmtError(e) - s = append(s, ns...) - if e == nil { - break - } - } - return strings.Join(s, "\n ") -} - -func innerFmtError(e error) ([]string, error) { - var s []string - var lines []string - switch e := e.(type) { - case ErrorNester: - lines = strings.Split(e.TopError(), "\n") - default: - lines = strings.Split(e.Error(), "\n") - } - for i, line := range lines { - if i == len(lines)-1 && len(line) == 0 { - // Don't output an empty line if caused by a trailing newline in - // the input. - break - } - if i == 0 { - s = append(s, line) - } else { - s = append(s, "> "+line) - } - } - return s, GetNestedError(e) -} - -// FmtErrors formats a slice of errors for logging. -func FmtErrors(es []error) string { - s := make([]string, 0, len(es)) - for _, e := range es { - s = append(s, e.Error()) - } - return strings.Join(s, "\n") -} diff --git a/pkg/private/serrors/errors_test.go b/pkg/private/serrors/errors_test.go index 38a261070..f62fce5cf 100644 --- a/pkg/private/serrors/errors_test.go +++ b/pkg/private/serrors/errors_test.go @@ -98,8 +98,8 @@ func TestWithCtx(t *testing.T) { t.Run("Is", func(t *testing.T) { err := serrors.New("simple err") errWithCtx := serrors.WithCtx(err, "someCtx", "someValue") - xtest.AssertErrorsIs(t, errWithCtx, err) - xtest.AssertErrorsIs(t, errWithCtx, errWithCtx) + assert.ErrorIs(t, errWithCtx, err) + assert.ErrorIs(t, errWithCtx, errWithCtx) }) t.Run("As", func(t *testing.T) { err := &testErrType{msg: "test err"} @@ -115,9 +115,9 @@ func TestWrap(t *testing.T) { err := serrors.New("simple err") msg := serrors.New("msg err") wrappedErr := serrors.Wrap(msg, err, "someCtx", "someValue") - xtest.AssertErrorsIs(t, wrappedErr, err) - xtest.AssertErrorsIs(t, wrappedErr, msg) - xtest.AssertErrorsIs(t, wrappedErr, wrappedErr) + assert.ErrorIs(t, wrappedErr, err) + assert.ErrorIs(t, wrappedErr, msg) + assert.ErrorIs(t, wrappedErr, wrappedErr) }) t.Run("As", func(t *testing.T) { err := &testErrType{msg: "test err"} @@ -135,8 +135,8 @@ func TestWrapStr(t *testing.T) { err := serrors.New("simple err") msg := "msg" wrappedErr := serrors.WrapStr(msg, err, "someCtx", "someValue") - xtest.AssertErrorsIs(t, wrappedErr, err) - xtest.AssertErrorsIs(t, wrappedErr, wrappedErr) + assert.ErrorIs(t, wrappedErr, err) + assert.ErrorIs(t, wrappedErr, wrappedErr) }) t.Run("As", func(t *testing.T) { err := &testErrType{msg: "test err"} @@ -153,14 +153,14 @@ func TestNew(t *testing.T) { t.Run("Is", func(t *testing.T) { err1 := serrors.New("err msg") err2 := serrors.New("err msg") - xtest.AssertErrorsIs(t, err1, err1) - xtest.AssertErrorsIs(t, err2, err2) + assert.ErrorIs(t, err1, err1) + assert.ErrorIs(t, err2, err2) assert.False(t, errors.Is(err1, err2)) assert.False(t, errors.Is(err2, err1)) err1 = serrors.New("err msg", "someCtx", "value") err2 = serrors.New("err msg", "someCtx", "value") - xtest.AssertErrorsIs(t, err1, err1) - xtest.AssertErrorsIs(t, err2, err2) + assert.ErrorIs(t, err1, err1) + assert.ErrorIs(t, err2, err2) assert.False(t, errors.Is(err1, err2)) assert.False(t, errors.Is(err2, err1)) }) diff --git a/pkg/private/util/BUILD.bazel b/pkg/private/util/BUILD.bazel index 0ee40d68a..117e0eba4 100644 --- a/pkg/private/util/BUILD.bazel +++ b/pkg/private/util/BUILD.bazel @@ -3,50 +3,31 @@ load("//tools/lint:go.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "aslist.go", - "checksum.go", - "docker.go", "duration.go", "duration_wrap.go", - "file.go", "file_mode.go", "fs.go", - "map.go", - "padding.go", - "raw.go", - "sync.go", "time.go", - "yaml.go", ], importpath = "github.com/scionproto/scion/pkg/private/util", visibility = ["//visibility:public"], deps = [ - "//pkg/addr:go_default_library", "//pkg/private/common:go_default_library", "//pkg/private/serrors:go_default_library", - "@in_gopkg_yaml_v2//:go_default_library", ], ) go_test( name = "go_default_test", srcs = [ - "aslist_test.go", - "checksum_test.go", "duration_test.go", "export_test.go", - "map_test.go", - "padding_test.go", "time_test.go", - "yaml_test.go", ], data = glob(["testdata/**"]), embed = [":go_default_library"], deps = [ - "//pkg/addr:go_default_library", - "//pkg/private/xtest:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", - "@in_gopkg_yaml_v2//:go_default_library", ], ) diff --git a/pkg/private/util/checksum.go b/pkg/private/util/checksum.go deleted file mode 100644 index 1a4dee6b9..000000000 --- a/pkg/private/util/checksum.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2017 ETH Zurich -// -// 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 util - -import ( - "unsafe" - - "github.com/scionproto/scion/pkg/private/common" -) - -// Calculate RFC1071 checksum of supplied data chunks. If a chunk has -// an odd length, it is padded with a 0 during checksum computation. -func Checksum(srcs ...[]byte) uint16 { - var sum uint32 - for _, src := range srcs { - length := len(src) - if length == 0 { - continue - } - length2 := length / 2 - // XXX(kormat): this creates a uint16 slice pointing to the underlying - // data in src. This provides a 2x speed-up, at least on - // linux/{amd64,arm64}. How it works: - // 1. Get the address of the backing array in src. - // 2. Cast the address to a uint16 _array_ (with a size guaranteed to - // be large enough). - // 3. Convert the array to a []uint16 of the appropriate number of - // uint16 elements (setting both length and cap). - // This has to be converted via an array, so that new slice metadata is - // allocated. Referencing a []uint8 as []uint16 will cause a crash. - src16 := (*[1 << 16]uint16)(unsafe.Pointer(&src[0]))[:length2:length2] - for i := 0; i < length2; i++ { - sum += uint32(src16[i]) - } - if length%2 != 0 { - sum += uint32(src[length-1]) - } - } - for sum > 0xffff { - sum = (sum >> 16) + (sum & 0xffff) - } - if !common.IsBigEndian { - // Native order is little-endian, so swap the bytes. - sum = (sum&0xFF)<<8 + (sum >> 8) - } - return ^uint16(sum) -} diff --git a/pkg/private/util/checksum_test.go b/pkg/private/util/checksum_test.go deleted file mode 100644 index 36ce0b2b1..000000000 --- a/pkg/private/util/checksum_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2017 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 util_test - -import ( - "encoding/binary" - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/scionproto/scion/pkg/private/util" -) - -func TestChecksum(t *testing.T) { - tests := []struct { - Input [][]byte - Output [2]byte - }{ - {[][]byte{{0x00, 0x01}}, [2]byte{0xff, 0xfe}}, - {[][]byte{{0x34, 0x88, 0x19, 0x55}}, [2]byte{0xb2, 0x22}}, - {[][]byte{{0x17, 0x00}}, [2]byte{0xe8, 0xff}}, - {[][]byte{{0x11, 0x11}}, [2]byte{0xee, 0xee}}, - {[][]byte{{0xef}}, [2]byte{0x10, 0xff}}, - {[][]byte{{0x11}, {0x80, 0x15, 0x13}}, - [2]byte{0x5b, 0xea}}, - {[][]byte{{0xa1, 0xa2, 0xa3, 0xa4}, - {0xb1, 0xb2, 0xb3}, - {0x10, 0x20}}, [2]byte{0x45, 0xe5}}, - } - for _, test := range tests { - checksum := make([]byte, 2) - binary.BigEndian.PutUint16(checksum, util.Checksum(test.Input...)) - t.Run(fmt.Sprintf("Input %v", test.Input), func(t *testing.T) { - assert.Equal(t, test.Output[:], checksum) - }) - } -} - -func BenchmarkChecksum(b *testing.B) { - data := make([]byte, 1500) - for i := 0; i < len(data); i++ { - data[i] = byte(i) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - util.Checksum(data) - } -} diff --git a/pkg/private/util/file.go b/pkg/private/util/file.go deleted file mode 100644 index 54e29a1a2..000000000 --- a/pkg/private/util/file.go +++ /dev/null @@ -1,47 +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 util - -import ( - "os" - "path" -) - -// WriteFile writes data to the file. It first writes to a temporary file -// in the same directory and the renames that file to filename. -func WriteFile(filename string, data []byte, perm os.FileMode) error { - dir, file := path.Split(filename) - tmp, err := os.CreateTemp(dir, file) - if err != nil { - return err - } - defer os.Remove(tmp.Name()) - if _, err := tmp.Write(data); err != nil { - return err - } - if err := tmp.Sync(); err != nil { - return err - } - if err := tmp.Chmod(perm); err != nil { - return err - } - if err := tmp.Close(); err != nil { - return err - } - if err := os.Rename(tmp.Name(), filename); err != nil { - return err - } - return nil -} diff --git a/pkg/private/util/map.go b/pkg/private/util/map.go deleted file mode 100644 index 80f1eef60..000000000 --- a/pkg/private/util/map.go +++ /dev/null @@ -1,28 +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 util - -import "strings" - -// LowerKeys lowers all keys in the map and deletes the previous keys. -func LowerKeys(m map[string]string) { - for k, v := range m { - lowerK := strings.ToLower(k) - if k != lowerK { - delete(m, k) - m[lowerK] = v - } - } -} diff --git a/pkg/private/util/map_test.go b/pkg/private/util/map_test.go deleted file mode 100644 index c703cbbcc..000000000 --- a/pkg/private/util/map_test.go +++ /dev/null @@ -1,68 +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 util_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/scionproto/scion/pkg/private/util" -) - -func TestLowerKeys(t *testing.T) { - t.Run("Nil map shouldn't do anything", func(t *testing.T) { - var m map[string]string - origMap := copyMap(m) - util.LowerKeys(m) - assert.Equal(t, origMap, m) - }) - - t.Run("Map with lowercase keys doesn't change", func(t *testing.T) { - m := map[string]string{ - "key1": "val1", - "key2": "val2", - } - origMap := copyMap(m) - util.LowerKeys(m) - assert.Equal(t, origMap, m) - }) - t.Run("Map with mixed keys changes", func(t *testing.T) { - m := map[string]string{ - "Key1": "val1", - "kEy2": "val2", - "key3": "val3", - } - util.LowerKeys(m) - expectedM := map[string]string{ - "key1": "val1", - "key2": "val2", - "key3": "val3", - } - assert.Equal(t, expectedM, m) - }) - -} - -func copyMap(m map[string]string) map[string]string { - if m == nil { - return nil - } - c := make(map[string]string, len(m)) - for k, v := range m { - c[k] = v - } - return c -} diff --git a/pkg/private/util/padding.go b/pkg/private/util/padding.go deleted file mode 100644 index 580a1cd13..000000000 --- a/pkg/private/util/padding.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 ETH Zurich -// -// 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 util - -// CalcPadding returns the number of padding bytes needed to round length bytes -// to a multiple of blkSize. -func CalcPadding(length, blkSize int) int { - spare := length % blkSize - if spare != 0 { - return blkSize - spare - } - return 0 -} - -func PaddedLen(length, blkSize int) int { - return length + CalcPadding(length, blkSize) -} - -func FillPadding(b []byte, length, blkSize int) int { - padding := CalcPadding(length, blkSize) - total := length + padding - for i := range b[length:total] { - b[length+i] = 0 - } - return total -} diff --git a/pkg/private/util/padding_test.go b/pkg/private/util/padding_test.go deleted file mode 100644 index fd80e85a4..000000000 --- a/pkg/private/util/padding_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2016 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 util_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/scionproto/scion/pkg/private/util" -) - -func TestCalcPadding(t *testing.T) { - cases := map[int]int{ - 0: 0, 1: 7, 2: 6, 3: 5, 4: 4, 5: 3, 6: 2, 7: 1, - 8: 0, 9: 7, 10: 6, 11: 5, 12: 4, 13: 3, 14: 2, 15: 1, - 16: 0, - } - for input, expected := range cases { - t.Run(fmt.Sprintf("Padding for %v should be %v", input, expected), func(t *testing.T) { - assert.Equal(t, expected, util.CalcPadding(input, 8), - "CalcPadding should calculate the correct padding (8B block size)") - }) - } -} diff --git a/pkg/private/util/raw.go b/pkg/private/util/raw.go deleted file mode 100644 index 356a4603a..000000000 --- a/pkg/private/util/raw.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2016 ETH Zurich -// -// 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 util - -import ( - "io" -) - -var _ io.ReadWriter = (*Raw)(nil) - -type Raw struct { - B []byte - Offset int -} - -func (r *Raw) Peek(p []byte) (int, error) { - if len(r.B[r.Offset:]) <= 0 { - return 0, io.EOF - } - return copy(p, r.B[r.Offset:]), nil -} - -func (r *Raw) Read(p []byte) (int, error) { - n, err := r.Peek(p) - if err == nil { - r.Offset += n - } - return n, err -} - -func (r *Raw) Write(p []byte) (int, error) { - if len(r.B[r.Offset:]) == 0 { - return 0, io.EOF - } - count := copy(r.B[r.Offset:], p) - r.Offset += count - return count, nil -} diff --git a/pkg/private/util/sync.go b/pkg/private/util/sync.go deleted file mode 100644 index d8f334ad3..000000000 --- a/pkg/private/util/sync.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2018 ETH Zurich -// -// 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 util - -import ( - "sync" - "time" -) - -// ChannelLock implements a sync.Mutex-like API that uses a 1-value channel -// behind the scenes. This makes it usable in selects that also need to meet -// context deadlines. -type ChannelLock struct { - ch chan struct{} -} - -func NewChannelLock() *ChannelLock { - ch := make(chan struct{}, 1) - ch <- struct{}{} - return &ChannelLock{ - ch: ch, - } -} - -// Lock returns a channel that can be drained to acquire the lock. -func (l *ChannelLock) Lock() <-chan struct{} { - return l.ch -} - -func (l *ChannelLock) Unlock() { - select { - case l.ch <- struct{}{}: - default: - // Programming error, double unlock - panic("double unlock") - } -} - -// Trigger represents a timer with delayed arming. Once Arm is called, the -// channel return by Done() will be closed after d time. If d is 0, the channel -// is never closed. -type Trigger struct { - d time.Duration - ch chan struct{} - once sync.Once -} - -func NewTrigger(d time.Duration) *Trigger { - return &Trigger{ - d: d, - ch: make(chan struct{}), - } -} - -func (t *Trigger) Done() <-chan struct{} { - return t.ch -} - -// Arm starts the trigger's preset timer, and returns the corresponding timer -// object. If the trigger is not configured with a timer, nil is returned. -// -// Calling Arm multiple times on the same object is a no-op. Every successive -// call will return nil. -func (t *Trigger) Arm() *time.Timer { - var timer *time.Timer - t.once.Do( - func() { - if t.d != 0 { - timer = time.AfterFunc(t.d, func() { close(t.ch) }) - } - }, - ) - return timer -} - -func (t *Trigger) Triggered() bool { - select { - case <-t.ch: - return true - default: - return false - } -} diff --git a/pkg/private/util/yaml.go b/pkg/private/util/yaml.go deleted file mode 100644 index d2c624d0e..000000000 --- a/pkg/private/util/yaml.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 ETH Zurich -// -// 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 util - -import ( - "encoding/base64" - "fmt" -) - -type B64Bytes []byte - -func (b B64Bytes) String() string { - return fmt.Sprintf("%x", []byte(b)) -} - -func (b B64Bytes) MarshalYAML() (interface{}, error) { - return base64.StdEncoding.EncodeToString(b), nil -} - -func (b *B64Bytes) UnmarshalYAML(unmarshal func(interface{}) error) error { - var s string - if err := unmarshal(&s); err != nil { - return err - } - data, err := base64.StdEncoding.DecodeString(s) - if err != nil { - return err - } - *b = B64Bytes(data) - return nil -} diff --git a/pkg/private/util/yaml_test.go b/pkg/private/util/yaml_test.go deleted file mode 100644 index 676785655..000000000 --- a/pkg/private/util/yaml_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2016 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 util_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v2" - - "github.com/scionproto/scion/pkg/private/util" -) - -// Interface assertions -var _ yaml.Marshaler = (*util.B64Bytes)(nil) -var _ yaml.Unmarshaler = (*util.B64Bytes)(nil) - -func Test_B64B_String(t *testing.T) { - b := util.B64Bytes{00, 01, 02, 03} - assert.Equal(t, "00010203", b.String(), "String() should return hex-encoded string") -} - -func Test_B64B_MarshalYAML(t *testing.T) { - b := util.B64Bytes("hello, world") - out, _ := yaml.Marshal(&b) - assert.Equal(t, "aGVsbG8sIHdvcmxk\n", string(out), - "Should marshal to a base64-encoded yaml entry") -} - -func Test_B64B_UnmarshalYAML_YAMLParseError(t *testing.T) { - var b util.B64Bytes - err := yaml.Unmarshal([]byte("a: b"), &b) - assert.Error(t, err, "YAML parse error") - assert.Zero(t, b) -} - -func Test_B64B_UnmarshalYAML_B64DecodeError(t *testing.T) { - var b util.B64Bytes - err := yaml.Unmarshal([]byte("_"), &b) - assert.Error(t, err, "Base64 decode error") - assert.Zero(t, b) -} - -func Test_B64B_UnmarshalYAML_Success(t *testing.T) { - var b util.B64Bytes - err := yaml.Unmarshal([]byte("aGVsbG8sIHdvcmxk"), &b) - if assert.NoError(t, err, "Valid sequence unmarshaled") { - assert.Equal(t, util.B64Bytes("hello, world"), b) - } -} diff --git a/pkg/private/xtest/BUILD.bazel b/pkg/private/xtest/BUILD.bazel index de40686df..02fa51536 100644 --- a/pkg/private/xtest/BUILD.bazel +++ b/pkg/private/xtest/BUILD.bazel @@ -3,11 +3,9 @@ load("//tools/lint:go.bzl", "go_library") go_library( name = "go_default_library", srcs = [ - "convey.go", "grpc.go", "helpers.go", "mocking.go", - "waiter.go", "x509.go", ], importpath = "github.com/scionproto/scion/pkg/private/xtest", @@ -16,7 +14,6 @@ go_library( "//pkg/addr:go_default_library", "//pkg/scrypto/cppki:go_default_library", "@af_inet_netaddr//:go_default_library", - "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//credentials:go_default_library", diff --git a/pkg/private/xtest/convey.go b/pkg/private/xtest/convey.go deleted file mode 100644 index 36cc026b7..000000000 --- a/pkg/private/xtest/convey.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2017 ETH Zurich -// -// 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 xtest implements common functionality for unit tests. -package xtest - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/assert" -) - -// AssertErrorsIs checks that errors.Is(actualErr, expectedErr) returns true, if -// expectedErr is not nil. -func AssertErrorsIs(t *testing.T, actualErr, expectedErr error) { - assert.True(t, errors.Is(actualErr, expectedErr), "Expect '%v' to be or contain '%v'", - actualErr, expectedErr) -} diff --git a/pkg/private/xtest/helpers.go b/pkg/private/xtest/helpers.go index 7f0b67265..406e1d910 100644 --- a/pkg/private/xtest/helpers.go +++ b/pkg/private/xtest/helpers.go @@ -20,17 +20,14 @@ import ( "encoding/hex" "encoding/json" "flag" - "fmt" "net" "os" - "os/exec" "path/filepath" "regexp" "strings" "testing" "time" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "inet.af/netaddr" @@ -132,22 +129,6 @@ func SanitizedName(t testing.TB) string { return strings.NewReplacer(" ", "_", "/", "_", "\\", "_", ":", "_").Replace(t.Name()) } -func TempDir(t testing.TB) (string, func()) { - name, err := os.MkdirTemp("", fmt.Sprintf("%s_*", SanitizedName(t))) - require.NoError(t, err) - return name, func() { - os.RemoveAll(name) - } -} - -// CopyDir copies "from" to "to", using the unix cp command. -func CopyDir(t testing.TB, from, to string) { - t.Helper() - cmd := exec.Command("cp", "-rL", from, to) - out, err := cmd.CombinedOutput() - require.NoError(t, err, string(out)) -} - // CopyFile copies the file. func CopyFile(t testing.TB, src, dst string) { t.Helper() @@ -157,15 +138,6 @@ func CopyFile(t testing.TB, src, dst string) { require.NoError(t, os.WriteFile(dst, raw, 0666)) } -// FailOnErr causes t to exit with a fatal error if err is non-nil. -func FailOnErr(t testing.TB, err error, desc ...string) { - t.Helper() - - if err != nil { - t.Fatal(strings.Join(desc, " "), err) - } -} - // MustMarshalJSONToFile marshals v and writes the result to file // testdata/baseName. If the file exists, it is truncated; if it doesn't exist, // it is created. On errors, t.Fatal() is called. @@ -371,12 +343,3 @@ func AssertReadDoesNotReturnBefore(t testing.TB, ch <-chan struct{}, timeout tim case <-time.After(timeout): } } - -// AssertError checks that err is not nil if expectError is true and that is it nil otherwise -func AssertError(t *testing.T, err error, expectError bool) { - if expectError { - assert.Error(t, err) - } else { - assert.NoError(t, err) - } -} diff --git a/pkg/private/xtest/mock_xtest/BUILD.bazel b/pkg/private/xtest/mock_xtest/BUILD.bazel deleted file mode 100644 index 98e509c7f..000000000 --- a/pkg/private/xtest/mock_xtest/BUILD.bazel +++ /dev/null @@ -1,18 +0,0 @@ -load("//tools/lint:go.bzl", "go_library") -load("@io_bazel_rules_go//go:def.bzl", "gomock") - -gomock( - name = "go_default_mock", - out = "mock.go", - interfaces = ["Callback"], - library = "//pkg/private/xtest:go_default_library", - package = "mock_xtest", -) - -go_library( - name = "go_default_library", - srcs = ["mock.go"], - importpath = "github.com/scionproto/scion/pkg/private/xtest/mock_xtest", - visibility = ["//visibility:public"], - deps = ["@com_github_golang_mock//gomock:go_default_library"], -) diff --git a/pkg/private/xtest/mock_xtest/mock.go b/pkg/private/xtest/mock_xtest/mock.go deleted file mode 100644 index 6c9e92c44..000000000 --- a/pkg/private/xtest/mock_xtest/mock.go +++ /dev/null @@ -1,46 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/scionproto/scion/pkg/private/xtest (interfaces: Callback) - -// Package mock_xtest is a generated GoMock package. -package mock_xtest - -import ( - reflect "reflect" - - gomock "github.com/golang/mock/gomock" -) - -// MockCallback is a mock of Callback interface. -type MockCallback struct { - ctrl *gomock.Controller - recorder *MockCallbackMockRecorder -} - -// MockCallbackMockRecorder is the mock recorder for MockCallback. -type MockCallbackMockRecorder struct { - mock *MockCallback -} - -// NewMockCallback creates a new mock instance. -func NewMockCallback(ctrl *gomock.Controller) *MockCallback { - mock := &MockCallback{ctrl: ctrl} - mock.recorder = &MockCallbackMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockCallback) EXPECT() *MockCallbackMockRecorder { - return m.recorder -} - -// Call mocks base method. -func (m *MockCallback) Call() { - m.ctrl.T.Helper() - m.ctrl.Call(m, "Call") -} - -// Call indicates an expected call of Call. -func (mr *MockCallbackMockRecorder) Call() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockCallback)(nil).Call)) -} diff --git a/pkg/private/xtest/mocking.go b/pkg/private/xtest/mocking.go index 5aa5c3903..c5e89c155 100644 --- a/pkg/private/xtest/mocking.go +++ b/pkg/private/xtest/mocking.go @@ -33,10 +33,3 @@ type PanickingReporter struct { func (reporter *PanickingReporter) Fatalf(format string, args ...interface{}) { panic(fmt.Sprintf(format, args...)) } - -// Callback defines an interfaces that provides a callback function that is -// mockable. A mock implementation implementing this interface can be found -// in sub-package mock_xtest. -type Callback interface { - Call() -} diff --git a/pkg/private/xtest/waiter.go b/pkg/private/xtest/waiter.go deleted file mode 100644 index 5b3f6fb75..000000000 --- a/pkg/private/xtest/waiter.go +++ /dev/null @@ -1,42 +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 xtest - -import ( - "sync" - "time" -) - -// Waiter wraps the waitgroup and allows waiting with timeouts. -type Waiter struct { - sync.WaitGroup -} - -// WaitWithTimeout returns immediately after the waitgroup is done, -// or the timeout has passed. The return value indicates whether -// the call timed out. -func (w *Waiter) WaitWithTimeout(timeout time.Duration) bool { - done := make(chan struct{}) - go func() { - defer close(done) - w.WaitGroup.Wait() - }() - select { - case <-done: - return false - case <-time.After(timeout): - return true - } -} diff --git a/pkg/scrypto/cppki/id_test.go b/pkg/scrypto/cppki/id_test.go index ed5725506..b9bf9cf1a 100644 --- a/pkg/scrypto/cppki/id_test.go +++ b/pkg/scrypto/cppki/id_test.go @@ -20,7 +20,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/scrypto/cppki" ) @@ -67,7 +66,7 @@ func TestTRCIDValidate(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() err := tc.ID.Validate() - xtest.AssertErrorsIs(t, err, tc.Err) + assert.ErrorIs(t, err, tc.Err) }) } diff --git a/pkg/scrypto/cppki/trc_test.go b/pkg/scrypto/cppki/trc_test.go index c9972d256..58485f763 100644 --- a/pkg/scrypto/cppki/trc_test.go +++ b/pkg/scrypto/cppki/trc_test.go @@ -184,7 +184,7 @@ func TestTRCValidateInvariant(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() err := tc.trc().Validate() - xtest.AssertErrorsIs(t, err, tc.err) + assert.ErrorIs(t, err, tc.err) }) } } diff --git a/pkg/scrypto/rand.go b/pkg/scrypto/rand.go index 74e57b927..b998d73ab 100644 --- a/pkg/scrypto/rand.go +++ b/pkg/scrypto/rand.go @@ -16,6 +16,7 @@ package scrypto import ( "crypto/rand" + "encoding/binary" mrand "math/rand" "github.com/scionproto/scion/pkg/private/common" @@ -38,7 +39,7 @@ func RandUint64() uint64 { // OS, and there's nothing we can do about it. panic("No random numbers available") } - return common.NativeOrder.Uint64(b) + return binary.LittleEndian.Uint64(b) } // RandInt64 returns a random int64 value. The returned value can be negative. diff --git a/pkg/slayers/BUILD.bazel b/pkg/slayers/BUILD.bazel index 232d4b342..c375215d3 100644 --- a/pkg/slayers/BUILD.bazel +++ b/pkg/slayers/BUILD.bazel @@ -45,7 +45,6 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/addr:go_default_library", - "//pkg/private/util:go_default_library", "//pkg/private/xtest:go_default_library", "//pkg/slayers/path:go_default_library", "//pkg/slayers/path/empty:go_default_library", diff --git a/pkg/slayers/scion_test.go b/pkg/slayers/scion_test.go index 3a9bf5639..c88e1be7d 100644 --- a/pkg/slayers/scion_test.go +++ b/pkg/slayers/scion_test.go @@ -24,7 +24,6 @@ import ( "github.com/stretchr/testify/require" "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path" @@ -487,6 +486,22 @@ func TestSCIONComputeChecksum(t *testing.T) { Protocol: 1, Checksum: 0x2615, }, + "IPv4/IPv4 odd length": { + Header: func(t *testing.T) *slayers.SCION { + s := &slayers.SCION{ + SrcIA: xtest.MustParseIA("1-ff00:0:110"), + DstIA: xtest.MustParseIA("1-ff00:0:112"), + } + err := s.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}) + require.NoError(t, err) + err = s.SetDstAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.2").To4()}) + require.NoError(t, err) + return s + }, + UpperLayer: xtest.MustParseHexString("aabbccddee"), + Protocol: 1, + Checksum: 0x3813, + }, "IPv4/IPv6": { Header: func(t *testing.T) *slayers.SCION { s := &slayers.SCION{ @@ -530,7 +545,10 @@ func TestSCIONComputeChecksum(t *testing.T) { ul := append([]byte{0, 0}, tc.UpperLayer...) // Reference checksum - reference := util.Checksum(pseudoHeader(t, s, len(ul), tc.Protocol), ul) + reference := referenceChecksum(append( + pseudoHeader(t, s, len(ul), tc.Protocol), + ul..., + )) // Compute checksum csum, err := s.ComputeChecksum(ul, tc.Protocol) @@ -558,3 +576,18 @@ func pseudoHeader(t *testing.T, s *slayers.SCION, upperLayerLength int, protocol binary.BigEndian.PutUint32(pseudo[offset:], uint32(protocol)) return pseudo } + +func referenceChecksum(data []byte) uint16 { + // pad at end with 0 + if len(data)%2 == 1 { + data = append(data, 0) + } + var csum uint32 + for i := 0; i+1 < len(data); i += 2 { + csum += uint32(binary.BigEndian.Uint16(data[i:])) + } + for csum > 0xffff { + csum = (csum >> 16) + (csum & 0xffff) + } + return ^uint16(csum) +} diff --git a/pkg/slayers/slayers_test.go b/pkg/slayers/slayers_test.go index 1373ce230..5833e45fc 100644 --- a/pkg/slayers/slayers_test.go +++ b/pkg/slayers/slayers_test.go @@ -24,7 +24,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path/empty" @@ -371,7 +370,10 @@ func TestSerializeSCIONUPDExtn(t *testing.T) { // checksum is set should result in 0. udpBuf := gopacket.NewSerializeBuffer() assert.NoError(t, gopacket.SerializeLayers(udpBuf, opts, u, pld)) - csum := util.Checksum(pseudoHeader(t, s, len(udpBuf.Bytes()), 17), udpBuf.Bytes()) + csum := referenceChecksum(append( + pseudoHeader(t, s, len(udpBuf.Bytes()), 17), + udpBuf.Bytes()..., + )) assert.Zero(t, csum) } diff --git a/pkg/sock/reliable/BUILD.bazel b/pkg/sock/reliable/BUILD.bazel index 290cff3f8..8a54bb26a 100644 --- a/pkg/sock/reliable/BUILD.bazel +++ b/pkg/sock/reliable/BUILD.bazel @@ -25,6 +25,7 @@ go_library( go_test( name = "go_default_test", srcs = [ + "errors_test.go", "frame_test.go", "packetizer_test.go", "registration_test.go", diff --git a/pkg/sock/reliable/errors.go b/pkg/sock/reliable/errors.go index aa30d0ddb..33a0ff9b9 100644 --- a/pkg/sock/reliable/errors.go +++ b/pkg/sock/reliable/errors.go @@ -15,9 +15,8 @@ package reliable import ( + "errors" "io" - "net" - "os" "syscall" "github.com/scionproto/scion/pkg/private/common" @@ -39,10 +38,7 @@ var ( ErrBufferTooSmall common.ErrMsg = "buffer too small" ) -// TODO(lukedirtwalker): Refactor methods in here to use `errors`. - func IsDispatcherError(err error) bool { - err = extractNestedError(err) // On Linux, the following errors should prompt a reconnect: // - An EOF, when a Read happens to a connection that was closed at the // other end, and there is no outstanding outgoing data. @@ -51,44 +47,8 @@ func IsDispatcherError(err error) bool { // - An ECONNRESET, when a Read happens to a connection that was // closed at the other end, and there is outstanding outgoing data. An // ECONNRESET may be followed by EOF on repeated attempts. - if err == io.EOF || - IsSpecificSysError(err, syscall.EPIPE) || - IsSpecificSysError(err, syscall.ECONNRESET) { - return true - } // All other errors can be immediately propagated back to the application. - return false -} - -// extractNestedError returns the innermost error of err. -func extractNestedError(err error) error { - if nestedError := common.GetNestedError(err); nestedError != nil { - return nestedError - } - return err -} - -func IsSpecificSysError(err error, errno syscall.Errno) bool { - serr, ok := getSysError(err) - if !ok { - return false - } - return serr.Err == errno -} - -func IsSysError(err error) bool { - _, ok := getSysError(err) - return ok -} - -func getSysError(err error) (*os.SyscallError, bool) { - nerr, ok := err.(*net.OpError) - if !ok { - return nil, false - } - serr, ok := nerr.Err.(*os.SyscallError) - if !ok { - return nil, false - } - return serr, true + return errors.Is(err, io.EOF) || + errors.Is(err, syscall.EPIPE) || + errors.Is(err, syscall.ECONNRESET) } diff --git a/pkg/sock/reliable/errors_test.go b/pkg/sock/reliable/errors_test.go new file mode 100644 index 000000000..097db199e --- /dev/null +++ b/pkg/sock/reliable/errors_test.go @@ -0,0 +1,75 @@ +// Copyright 2022 SCION Association +// +// 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 reliable_test + +import ( + "fmt" + "io" + "net" + "os" + "syscall" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/scionproto/scion/pkg/sock/reliable" +) + +func TestIsDispatcherError(t *testing.T) { + cases := map[string]struct { + err error + expected bool + }{ + "nil": { + err: nil, + expected: false, + }, + "io.EOF": { + err: io.EOF, + expected: true, + }, + "io.EOF wrapped": { + err: fmt.Errorf("aha, end of the file %w", io.EOF), + expected: true, + }, + "syscall EPIPE": { + err: syscall.EPIPE, + expected: true, + }, + "OpError EPIPE": { + err: &net.OpError{Err: &os.SyscallError{Err: syscall.EPIPE}}, + expected: true, + }, + "Wrapped OpError EPIPE": { + err: fmt.Errorf("foo %w", + &net.OpError{Err: &os.SyscallError{Err: syscall.ECONNRESET}}), + expected: true, + }, + "OpError ECONNRESET": { + err: &net.OpError{Err: &os.SyscallError{Err: syscall.ECONNRESET}}, + expected: true, + }, + "OpError other errno": { + err: &net.OpError{Err: &os.SyscallError{Err: syscall.EACCES}}, + expected: false, + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + actual := reliable.IsDispatcherError(c.err) + assert.Equal(t, c.expected, actual, c.err) + }) + } +} diff --git a/pkg/sock/reliable/frame_test.go b/pkg/sock/reliable/frame_test.go index 339432bdc..a93dfe055 100644 --- a/pkg/sock/reliable/frame_test.go +++ b/pkg/sock/reliable/frame_test.go @@ -19,8 +19,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - - "github.com/scionproto/scion/pkg/private/xtest" ) func TestUnderlayPacketSerializeTo(t *testing.T) { @@ -101,7 +99,7 @@ func TestUnderlayPacketSerializeTo(t *testing.T) { t.Run(tc.Name, func(t *testing.T) { b := make([]byte, 1500) n, err := tc.Packet.SerializeTo(b) - xtest.AssertErrorsIs(t, err, tc.ExpectedError) + assert.ErrorIs(t, err, tc.ExpectedError) assert.Equal(t, tc.ExpectedData, b[:n]) }) } @@ -187,7 +185,7 @@ func TestUnderlayPacketDecodeFromBytes(t *testing.T) { t.Run(tc.Name, func(t *testing.T) { var p UnderlayPacket err := p.DecodeFromBytes(tc.Buffer) - xtest.AssertErrorsIs(t, err, tc.ExpectedError) + assert.ErrorIs(t, err, tc.ExpectedError) assert.Equal(t, tc.ExpectedPacket, p) }) } diff --git a/pkg/sock/reliable/reconnect/BUILD.bazel b/pkg/sock/reliable/reconnect/BUILD.bazel index 5a5624299..0ef4bfcc8 100644 --- a/pkg/sock/reliable/reconnect/BUILD.bazel +++ b/pkg/sock/reliable/reconnect/BUILD.bazel @@ -43,5 +43,6 @@ go_test( "//pkg/sock/reliable/reconnect/mock_reconnect:go_default_library", "@com_github_golang_mock//gomock:go_default_library", "@com_github_smartystreets_goconvey//convey:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", ], ) diff --git a/pkg/sock/reliable/reconnect/conn_io_test.go b/pkg/sock/reliable/reconnect/conn_io_test.go index 2d0f25fea..3e618b13f 100644 --- a/pkg/sock/reliable/reconnect/conn_io_test.go +++ b/pkg/sock/reliable/reconnect/conn_io_test.go @@ -22,6 +22,7 @@ import ( "github.com/golang/mock/gomock" . "github.com/smartystreets/goconvey/convey" + "github.com/stretchr/testify/assert" "github.com/scionproto/scion/pkg/private/mocks/net/mock_net" "github.com/scionproto/scion/pkg/private/xtest" @@ -59,7 +60,7 @@ func TestPacketConnIO(t *testing.T) { Convey("IO must return non-dispatcher errors", func() { mockIO.EXPECT().Do(mockConn).Return(writeNonDispatcherError) err := packetConn.DoIO(mockIO) - xtest.AssertErrorsIs(t, err, writeNonDispatcherError) + assert.ErrorIs(t, err, writeNonDispatcherError) }) Convey("IO must return an error if reconnect got an error from the dispatcher", func() { // If reconnection failed while the dispatcher was up (e.g., diff --git a/pkg/sock/reliable/reconnect/reconnecter.go b/pkg/sock/reliable/reconnect/reconnecter.go index 0b1ae18f2..d5d36cec6 100644 --- a/pkg/sock/reliable/reconnect/reconnecter.go +++ b/pkg/sock/reliable/reconnect/reconnecter.go @@ -16,12 +16,13 @@ package reconnect import ( "context" + "errors" "net" + "os" "sync" "time" "github.com/scionproto/scion/pkg/log" - "github.com/scionproto/scion/pkg/sock/reliable" ) // Use a var here to allow tests to inject shorter intervals for fast testing. @@ -81,8 +82,9 @@ func (r *TickingReconnecter) Reconnect(ctx context.Context) (net.PacketConn, uin return nil, 0, ErrReconnecterTimeoutExpired } conn, port, err := r.reconnectF(newTimeout) + var sysErr *os.SyscallError switch { - case reliable.IsSysError(err): + case errors.As(err, &sysErr): // Wait until next tick to retry. If the overall timeout expires // before the next tick, return immediately with an error. // time.Ticker will ensure that no more than one attempt is made diff --git a/pkg/sock/reliable/registration_test.go b/pkg/sock/reliable/registration_test.go index 97dbabe99..0cf96e416 100644 --- a/pkg/sock/reliable/registration_test.go +++ b/pkg/sock/reliable/registration_test.go @@ -109,7 +109,7 @@ func TestRegistrationMessageSerializeTo(t *testing.T) { t.Run(tc.Name, func(t *testing.T) { b := make([]byte, 1500) n, err := tc.Registration.SerializeTo(b) - xtest.AssertErrorsIs(t, err, tc.ExpectedError) + assert.ErrorIs(t, err, tc.ExpectedError) assert.Equal(t, tc.ExpectedData, b[:n]) }) } @@ -240,7 +240,7 @@ func TestRegistrationMessageDecodeFromBytes(t *testing.T) { t.Run(tc.Name, func(t *testing.T) { var r Registration err := r.DecodeFromBytes(tc.Data) - xtest.AssertErrorsIs(t, err, tc.ExpectedError) + assert.ErrorIs(t, err, tc.ExpectedError) assert.Equal(t, tc.ExpectedRegistration, r) }) } @@ -251,7 +251,7 @@ func TestConfirmationMessageSerializeTo(t *testing.T) { t.Run("bad buffer", func(t *testing.T) { b := make([]byte, 1) n, err := confirmation.SerializeTo(b) - xtest.AssertErrorsIs(t, err, ErrBufferTooSmall) + assert.ErrorIs(t, err, ErrBufferTooSmall) assert.Zero(t, n) }) t.Run("success", func(t *testing.T) { @@ -267,7 +267,7 @@ func TestConfirmationDecodeFromBytes(t *testing.T) { t.Run("bad buffer", func(t *testing.T) { b := []byte{0xaa} err := confirmation.DecodeFromBytes(b) - xtest.AssertErrorsIs(t, err, ErrIncompletePort) + assert.ErrorIs(t, err, ErrIncompletePort) assert.Equal(t, Confirmation{}, confirmation) }) t.Run("success", func(t *testing.T) { diff --git a/private/env/BUILD.bazel b/private/env/BUILD.bazel index 2a4192a2c..796ad79db 100644 --- a/private/env/BUILD.bazel +++ b/private/env/BUILD.bazel @@ -3,6 +3,7 @@ load("//tools/lint:go.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "docker.go", "env.go", "features.go", "logging.go", diff --git a/pkg/private/util/docker.go b/private/env/docker.go similarity index 98% rename from pkg/private/util/docker.go rename to private/env/docker.go index dcb249763..e9a325678 100644 --- a/pkg/private/util/docker.go +++ b/private/env/docker.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package util +package env import ( "bufio" diff --git a/private/env/logging.go b/private/env/logging.go index 965be46a7..9c2c67569 100644 --- a/private/env/logging.go +++ b/private/env/logging.go @@ -20,7 +20,6 @@ import ( "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/serrors" - "github.com/scionproto/scion/pkg/private/util" ) // Startup* variables are set during link time. @@ -32,7 +31,7 @@ var ( // LogAppStarted should be called by applications as soon as logging is // initialized. func LogAppStarted(svcType, elemID string) error { - inDocker, err := util.RunsInDocker() + inDocker, err := RunsInDocker() if err != nil { return serrors.WrapStr("Unable to determine if running in docker", err) } diff --git a/private/path/combinator/BUILD.bazel b/private/path/combinator/BUILD.bazel index 22d437df0..fdd55e4ad 100644 --- a/private/path/combinator/BUILD.bazel +++ b/private/path/combinator/BUILD.bazel @@ -45,5 +45,6 @@ go_test( "//pkg/snet/path:go_default_library", "@com_github_golang_mock//gomock:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", ], ) diff --git a/private/path/combinator/combinator_test.go b/private/path/combinator/combinator_test.go index 6ab0a180e..8f5e43960 100644 --- a/private/path/combinator/combinator_test.go +++ b/private/path/combinator/combinator_test.go @@ -25,6 +25,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/common" @@ -86,7 +87,7 @@ func TestBadPeering(t *testing.T) { txtResult := writePaths(result) if *update { err := os.WriteFile(xtest.ExpandPath(tc.FileName), txtResult.Bytes(), 0644) - xtest.FailOnErr(t, err) + require.NoError(t, err) } expected, err := os.ReadFile(xtest.ExpandPath(tc.FileName)) assert.NoError(t, err) @@ -132,7 +133,7 @@ func TestMultiPeering(t *testing.T) { txtResult := writePaths(result) if *update { err := os.WriteFile(xtest.ExpandPath(tc.FileName), txtResult.Bytes(), 0644) - xtest.FailOnErr(t, err) + require.NoError(t, err) } expected, err := os.ReadFile(xtest.ExpandPath(tc.FileName)) assert.NoError(t, err) @@ -175,7 +176,7 @@ func TestSameCoreParent(t *testing.T) { txtResult := writePaths(result) if *update { err := os.WriteFile(xtest.ExpandPath(tc.FileName), txtResult.Bytes(), 0644) - xtest.FailOnErr(t, err) + require.NoError(t, err) } expected, err := os.ReadFile(xtest.ExpandPath(tc.FileName)) assert.NoError(t, err) @@ -226,7 +227,7 @@ func TestLoops(t *testing.T) { txtResult := writePaths(result) if *update { err := os.WriteFile(xtest.ExpandPath(tc.FileName), txtResult.Bytes(), 0644) - xtest.FailOnErr(t, err) + require.NoError(t, err) } expected, err := os.ReadFile(xtest.ExpandPath(tc.FileName)) assert.NoError(t, err) @@ -533,7 +534,7 @@ func TestComputePath(t *testing.T) { txtResult := writePaths(result) if *update { err := os.WriteFile(xtest.ExpandPath(tc.FileName), txtResult.Bytes(), 0644) - xtest.FailOnErr(t, err) + require.NoError(t, err) } expected, err := os.ReadFile(xtest.ExpandPath(tc.FileName)) assert.NoError(t, err) diff --git a/private/path/pathpol/acl_test.go b/private/path/pathpol/acl_test.go index 37ea255ce..080c14533 100644 --- a/private/path/pathpol/acl_test.go +++ b/private/path/pathpol/acl_test.go @@ -52,7 +52,7 @@ func TestNewACL(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { acl, err := NewACL(test.Entries...) - xtest.AssertErrorsIs(t, err, test.ExpectedErr) + assert.ErrorIs(t, err, test.ExpectedErr) if test.ExpectedErr == nil { assert.NotNil(t, acl) } diff --git a/private/path/pathpol/policy_test.go b/private/path/pathpol/policy_test.go index 515233e20..9f32d887a 100644 --- a/private/path/pathpol/policy_test.go +++ b/private/path/pathpol/policy_test.go @@ -625,7 +625,7 @@ func TestPolicyJsonConversion(t *testing.T) { func newSequence(t *testing.T, str string) *Sequence { seq, err := NewSequence(str) - xtest.FailOnErr(t, err) + require.NoError(t, err) return seq } @@ -669,6 +669,6 @@ func (p PathProvider) GetPaths(src, dst addr.IA) []snet.Path { func mustHopPredicate(t *testing.T, str string) *HopPredicate { hp, err := HopPredicateFromString(str) - xtest.FailOnErr(t, err) + require.NoError(t, err) return hp } diff --git a/private/revcache/revcachetest/BUILD.bazel b/private/revcache/revcachetest/BUILD.bazel index 0043af6b6..cbd076971 100644 --- a/private/revcache/revcachetest/BUILD.bazel +++ b/private/revcache/revcachetest/BUILD.bazel @@ -14,5 +14,6 @@ go_library( "//pkg/private/xtest:go_default_library", "//private/revcache:go_default_library", "@com_github_smartystreets_goconvey//convey:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", ], ) diff --git a/private/revcache/revcachetest/revcachetest.go b/private/revcache/revcachetest/revcachetest.go index 6f8e2438e..01764533f 100644 --- a/private/revcache/revcachetest/revcachetest.go +++ b/private/revcache/revcachetest/revcachetest.go @@ -21,6 +21,7 @@ import ( "time" . "github.com/smartystreets/goconvey/convey" + "github.com/stretchr/testify/require" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/common" @@ -109,13 +110,13 @@ func testGetMultikey(t *testing.T, revCache TestableRevCache) { SoMsg("Should return no revs", revs, ShouldBeEmpty) _, err = revCache.Insert(ctx, rev1) - xtest.FailOnErr(t, err) + require.NoError(t, err) _, err = revCache.Insert(ctx, rev2) - xtest.FailOnErr(t, err) + require.NoError(t, err) _, err = revCache.Insert(ctx, rev3) - xtest.FailOnErr(t, err) + require.NoError(t, err) _, err = revCache.Insert(ctx, rev4) - xtest.FailOnErr(t, err) + require.NoError(t, err) key1 := *revcache.NewKey(ia110, ifId15) revs, err = revCache.Get(ctx, revcache.KeySet{key1: {}}) @@ -153,13 +154,13 @@ func testGetAll(t *testing.T, revCache TestableRevCache) { rev3 := defaultRevInfo(ia120, ifId15) rev4 := defaultRevInfo(ia120, common.IFIDType(20)) _, err = revCache.Insert(ctx, rev1) - xtest.FailOnErr(t, err) + require.NoError(t, err) _, err = revCache.Insert(ctx, rev2) - xtest.FailOnErr(t, err) + require.NoError(t, err) _, err = revCache.Insert(ctx, rev3) - xtest.FailOnErr(t, err) + require.NoError(t, err) _, err = revCache.Insert(ctx, rev4) - xtest.FailOnErr(t, err) + require.NoError(t, err) expectedRevs := []*path_mgmt.RevInfo{rev1, rev2, rev3, rev4} @@ -221,7 +222,7 @@ func testInsertNewer(t *testing.T, revCache TestableRevCache) { ctx, cancelF := context.WithTimeout(context.Background(), TimeOut) defer cancelF() _, err := revCache.Insert(ctx, rev) - xtest.FailOnErr(t, err) + require.NoError(t, err) revNew := &path_mgmt.RevInfo{ IfID: ifId15, RawIsdas: ia110, @@ -229,7 +230,7 @@ func testInsertNewer(t *testing.T, revCache TestableRevCache) { RawTimestamp: util.TimeToSecs(time.Now().Add(10 * time.Second)), RawTTL: uint32((time.Duration(10) * time.Second).Seconds()), } - xtest.FailOnErr(t, err) + require.NoError(t, err) inserted, err := revCache.Insert(ctx, revNew) SoMsg("Insert should return true for a new entry", inserted, ShouldBeTrue) SoMsg("Insert a new entry should not err", err, ShouldBeNil) diff --git a/private/service/BUILD.bazel b/private/service/BUILD.bazel index fa230b821..d6556be92 100644 --- a/private/service/BUILD.bazel +++ b/private/service/BUILD.bazel @@ -8,7 +8,6 @@ go_library( deps = [ "//pkg/log:go_default_library", "//pkg/private/serrors:go_default_library", - "//pkg/private/util:go_default_library", "//private/env:go_default_library", "//private/topology:go_default_library", "@com_github_pelletier_go_toml//:go_default_library", diff --git a/private/service/statuspages.go b/private/service/statuspages.go index a90d2b38d..3e6de3279 100644 --- a/private/service/statuspages.go +++ b/private/service/statuspages.go @@ -28,7 +28,6 @@ import ( "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/serrors" - "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/private/env" "github.com/scionproto/scion/private/topology" ) @@ -143,7 +142,7 @@ func NewConfigStatusPage(config interface{}) StatusPage { func NewInfoStatusPage() StatusPage { handler := func(w http.ResponseWriter, r *http.Request) { info := env.VersionInfo() - inDocker, err := util.RunsInDocker() + inDocker, err := env.RunsInDocker() if err == nil { info += fmt.Sprintf(" In docker: %v\n", inDocker) } diff --git a/private/trust/router_test.go b/private/trust/router_test.go index 94e11249c..2f2f80eaf 100644 --- a/private/trust/router_test.go +++ b/private/trust/router_test.go @@ -151,7 +151,7 @@ func TestCSRouterChooseServer(t *testing.T) { } res, err := router.ChooseServer(context.Background(), test.ISD) if test.ExpectedErr != nil { - xtest.AssertErrorsIs(t, err, test.ExpectedErr) + assert.ErrorIs(t, err, test.ExpectedErr) } else { require.NoError(t, err) expected := &snet.SVCAddr{ diff --git a/tools/end2end_integration/main.go b/tools/end2end_integration/main.go index f4daa7383..6c3b5883a 100644 --- a/tools/end2end_integration/main.go +++ b/tools/end2end_integration/main.go @@ -304,11 +304,16 @@ func getPairs() ([]integration.IAPair, error) { if len(parts) != 2 { return nil, serrors.New("Invalid subset", "subset", subset) } - return filter(parts[0], parts[1], pairs, integration.ASList), nil + return filter(parts[0], parts[1], pairs, integration.LoadedASList), nil } // filter returns the list of ASes that are part of the desired subset. -func filter(src, dst string, pairs []integration.IAPair, ases *util.ASList) []integration.IAPair { +func filter( + src, dst string, + pairs []integration.IAPair, + ases *integration.ASList, +) []integration.IAPair { + var res []integration.IAPair s, err1 := addr.ParseIA(src) d, err2 := addr.ParseIA(dst) @@ -333,7 +338,7 @@ func filter(src, dst string, pairs []integration.IAPair, ases *util.ASList) []in return res } -func contains(ases *util.ASList, core bool, ia addr.IA) bool { +func contains(ases *integration.ASList, core bool, ia addr.IA) bool { l := ases.Core if !core { l = ases.NonCore diff --git a/tools/integration/BUILD.bazel b/tools/integration/BUILD.bazel index 4c37739d4..cfe67524a 100644 --- a/tools/integration/BUILD.bazel +++ b/tools/integration/BUILD.bazel @@ -1,8 +1,9 @@ -load("//tools/lint:go.bzl", "go_library") +load("//tools/lint:go.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "aslist.go", "binary.go", "cmd.go", "docker.go", @@ -18,7 +19,6 @@ go_library( "//pkg/log:go_default_library", "//pkg/private/common:go_default_library", "//pkg/private/serrors:go_default_library", - "//pkg/private/util:go_default_library", "//pkg/snet:go_default_library", "//private/topology:go_default_library", "//tools/integration/progress:go_default_library", @@ -27,3 +27,15 @@ go_library( ) exports_files(["bin_wrapper.sh"]) + +go_test( + name = "go_default_test", + srcs = ["aslist_test.go"], + data = glob(["testdata/**"]), + deps = [ + ":go_default_library", + "//pkg/addr:go_default_library", + "//pkg/private/xtest:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", + ], +) diff --git a/pkg/private/util/aslist.go b/tools/integration/aslist.go similarity index 98% rename from pkg/private/util/aslist.go rename to tools/integration/aslist.go index e0f11747a..dbf43d128 100644 --- a/pkg/private/util/aslist.go +++ b/tools/integration/aslist.go @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package util +package integration import ( "os" diff --git a/pkg/private/util/aslist_test.go b/tools/integration/aslist_test.go similarity index 88% rename from pkg/private/util/aslist_test.go rename to tools/integration/aslist_test.go index 14c2e1742..17bef426e 100644 --- a/pkg/private/util/aslist_test.go +++ b/tools/integration/aslist_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package util_test +package integration_test import ( "testing" @@ -20,15 +20,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" + "github.com/scionproto/scion/tools/integration" ) func TestLoadASList(t *testing.T) { tests := map[string]struct { File string Error assert.ErrorAssertionFunc - Expected *util.ASList + Expected *integration.ASList }{ "non-existing file": { File: "doesntexist.yml", @@ -41,7 +41,7 @@ func TestLoadASList(t *testing.T) { "valid file": { File: "testdata/aslist_valid.yml", Error: assert.NoError, - Expected: &util.ASList{ + Expected: &integration.ASList{ Core: []addr.IA{xtest.MustParseIA("1-ff00:0:110")}, NonCore: []addr.IA{ xtest.MustParseIA("1-ff00:0:111"), @@ -52,7 +52,7 @@ func TestLoadASList(t *testing.T) { } for name, test := range tests { t.Run(name, func(t *testing.T) { - asList, err := util.LoadASList(test.File) + asList, err := integration.LoadASList(test.File) test.Error(t, err) assert.Equal(t, test.Expected, asList) }) diff --git a/tools/integration/integration.go b/tools/integration/integration.go index 04f89f3da..244622eb4 100644 --- a/tools/integration/integration.go +++ b/tools/integration/integration.go @@ -35,7 +35,6 @@ import ( "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/serrors" - "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/snet" "github.com/scionproto/scion/private/topology" ) @@ -55,8 +54,8 @@ const ( ) var ( - // ASList exposes the loaded ASList. - ASList *util.ASList + // LoadedASList exposes the ASList loaded during Init + LoadedASList *ASList ) type iaArgs []addr.IA @@ -156,15 +155,15 @@ func validateFlags() error { return err } var err error - ASList, err = util.LoadASList(GenFile("as_list.yml")) + LoadedASList, err = LoadASList(GenFile("as_list.yml")) if err != nil { return err } if len(srcIAs) == 0 { - srcIAs = ASList.AllASes() + srcIAs = LoadedASList.AllASes() } if len(dstIAs) == 0 { - dstIAs = ASList.AllASes() + dstIAs = LoadedASList.AllASes() } return nil } diff --git a/pkg/private/util/testdata/aslist_invalid.yml b/tools/integration/testdata/aslist_invalid.yml similarity index 100% rename from pkg/private/util/testdata/aslist_invalid.yml rename to tools/integration/testdata/aslist_invalid.yml diff --git a/pkg/private/util/testdata/aslist_valid.yml b/tools/integration/testdata/aslist_valid.yml similarity index 100% rename from pkg/private/util/testdata/aslist_valid.yml rename to tools/integration/testdata/aslist_valid.yml From 3590d24ce6778fad1d6735ec7cc993222b82b4ab Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 9 Feb 2023 17:42:25 +0100 Subject: [PATCH 005/255] control: cached loading of keys/certs from disk for TLS (#4281) Previously only the keys were loaded from disk, the chains were fetched from the DB. This becomes a problem with certificate renewal (especially when overwriting the key/cert files) because the new key is loaded from the disk but no corresponding certificate is loaded into the DB Additionally, loading certs from disk for each individual TLS session establishment is not ideal, so we should have a cache. Removed the separate X509KeyPairLoader and replaced it with trust.SignerGen (extended to allow filtering certificates for key usage). For this SignerGen, a CachingSignerGen implementation already exists. The new TLSCertificateLoader wraps this SignerGen and converts the resulting Signer to a tls.Certificate. Loading the certificates is no longer part of trust.TLSCryptoManager. Thus, rename TLSCryptoManager to TLSCryptoVerifier. --- control/cmd/control/main.go | 26 +- control/drkey/grpc/fetcher_test.go | 27 +- control/trust.go | 53 +- control/trust/BUILD.bazel | 1 + control/trust/signer_gen_test.go | 58 +- control/trust/tls_loader.go | 70 ++ control/trust_test.go | 3 +- private/app/appnet/infraenv.go | 16 +- private/trust/BUILD.bazel | 6 +- private/trust/mock_trust/BUILD.bazel | 1 - private/trust/mock_trust/mock.go | 56 +- private/trust/signer_gen.go | 20 + .../{tls_handshake.go => tls_verifier.go} | 66 +- ...handshake_test.go => tls_verifier_test.go} | 33 +- private/trust/x509_provider.go | 153 --- private/trust/x509_provider_test.go | 926 ------------------ 16 files changed, 233 insertions(+), 1282 deletions(-) create mode 100644 control/trust/tls_loader.go rename private/trust/{tls_handshake.go => tls_verifier.go} (65%) rename private/trust/{tls_handshake_test.go => tls_verifier_test.go} (84%) delete mode 100644 private/trust/x509_provider.go delete mode 100644 private/trust/x509_provider_test.go diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index 7fd058a77..4dd447cb5 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -16,6 +16,7 @@ package main import ( "context" + "crypto/x509" "encoding/json" "errors" "fmt" @@ -199,20 +200,19 @@ func realMain(ctx context.Context) error { return err } - loader := trust.X509KeyPairProvider{ - IA: topo.IA(), - DB: trustDB, - KeyLoader: cstrust.LoadingRing{ - Dir: filepath.Join(globalCfg.General.ConfigDir, "crypto/as"), - }, - } nc := infraenv.NetworkConfig{ IA: topo.IA(), Public: topo.ControlServiceAddress(globalCfg.General.ID), ReconnectToDispatcher: globalCfg.General.ReconnectToDispatcher, QUIC: infraenv.QUIC{ - Address: globalCfg.QUIC.Address, - TLSManager: trust.NewTLSCryptoManager(loader, trustDB), + Address: globalCfg.QUIC.Address, + TLSVerifier: trust.NewTLSCryptoVerifier(trustDB), + GetCertificate: cs.NewTLSCertificateLoader( + topo.IA(), x509.ExtKeyUsageServerAuth, trustDB, globalCfg.General.ConfigDir, + ).GetCertificate, + GetClientCertificate: cs.NewTLSCertificateLoader( + topo.IA(), x509.ExtKeyUsageClientAuth, trustDB, globalCfg.General.ConfigDir, + ).GetClientCertificate, }, SVCResolver: topo, SCMPHandler: snet.DefaultSCMPHandler{ @@ -384,10 +384,7 @@ func realMain(ctx context.Context) error { } - signer, err := cs.NewSigner(topo.IA(), trustDB, globalCfg.General.ConfigDir) - if err != nil { - return serrors.WrapStr("initializing AS signer", err) - } + signer := cs.NewSigner(topo.IA(), trustDB, globalCfg.General.ConfigDir) var chainBuilder renewal.ChainBuilder var caClient *caapi.Client @@ -622,6 +619,7 @@ func realMain(ctx context.Context) error { }, } defer level1DB.Close() + drkeyFetcher := drkeygrpc.Fetcher{ Dialer: &libgrpc.QUICDialer{ Rewriter: nc.AddressRewriter(nil), @@ -643,7 +641,7 @@ func realMain(ctx context.Context) error { } drkeyService := &drkeygrpc.Server{ LocalIA: topo.IA(), - ClientCertificateVerifier: nc.QUIC.TLSManager, + ClientCertificateVerifier: nc.QUIC.TLSVerifier, Engine: drkeyEngine, AllowedSVHostProto: globalCfg.DRKey.Delegation.ToAllowedSet(), } diff --git a/control/drkey/grpc/fetcher_test.go b/control/drkey/grpc/fetcher_test.go index e93db1cd5..fc1d919f1 100644 --- a/control/drkey/grpc/fetcher_test.go +++ b/control/drkey/grpc/fetcher_test.go @@ -64,12 +64,9 @@ func TestLevel1KeyFetching(t *testing.T) { lvl1db := mock_grpc.NewMockEngine(ctrl) lvl1db.EXPECT().DeriveLevel1(gomock.Any()).AnyTimes().Return(drkey.Level1Key{}, nil) - mgrdb := mock_trust.NewMockDB(ctrl) - mgrdb.EXPECT().SignedTRC(gomock.Any(), gomock.Any()).AnyTimes().Return(trc, nil) - loader := mock_trust.NewMockX509KeyPairLoader(ctrl) - loader.EXPECT().LoadClientKeyPair(gomock.Any()).AnyTimes().Return(&tlsCert, nil) - loader.EXPECT().LoadServerKeyPair(gomock.Any()).AnyTimes().Return(&tlsCert, nil) - mgr := trust.NewTLSCryptoManager(loader, mgrdb) + db := mock_trust.NewMockDB(ctrl) + db.EXPECT().SignedTRC(gomock.Any(), gomock.Any()).AnyTimes().Return(trc, nil) + verifier := trust.NewTLSCryptoVerifier(db) path := mock_snet.NewMockPath(ctrl) path.EXPECT().Metadata().AnyTimes().Return(&snet.PathMetadata{ @@ -102,17 +99,21 @@ func TestLevel1KeyFetching(t *testing.T) { // credentials for individual calls so that server does not need to be // recreated here. serverCreds := credentials.NewTLS(&tls.Config{ - InsecureSkipVerify: true, - GetCertificate: mgr.GetCertificate, + InsecureSkipVerify: true, + GetCertificate: func(*tls.ClientHelloInfo) (*tls.Certificate, error) { + return &tlsCert, nil + }, VerifyPeerCertificate: nil, // certificate verified in the service ClientAuth: tls.RequestClientCert, }) clientTLSConfig := &tls.Config{ - InsecureSkipVerify: true, - GetClientCertificate: mgr.GetClientCertificate, - VerifyPeerCertificate: mgr.VerifyServerCertificate, - VerifyConnection: mgr.VerifyConnection, + InsecureSkipVerify: true, + GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { + return &tlsCert, nil + }, + VerifyPeerCertificate: verifier.VerifyServerCertificate, + VerifyConnection: verifier.VerifyConnection, } if tc.omitClientCert { clientTLSConfig.GetClientCertificate = nil @@ -122,7 +123,7 @@ func TestLevel1KeyFetching(t *testing.T) { server := xtest.NewGRPCService(xtest.WithCredentials(clientCreds, serverCreds)) cppb.RegisterDRKeyInterServiceServer(server.Server(), &dk_grpc.Server{ Engine: lvl1db, - ClientCertificateVerifier: mgr, + ClientCertificateVerifier: verifier, }) server.Start(t) diff --git a/control/trust.go b/control/trust.go index 1ca1b1a77..c05087b90 100644 --- a/control/trust.go +++ b/control/trust.go @@ -16,6 +16,7 @@ package control import ( "context" + "crypto/x509" "errors" "path/filepath" "time" @@ -64,8 +65,42 @@ func LoadTrustMaterial(ctx context.Context, configDir string, db trust.DB) error return nil } +func NewTLSCertificateLoader( + ia addr.IA, + extKeyUsage x509.ExtKeyUsage, + db trust.DB, + cfgDir string, +) cstrust.TLSCertificateLoader { + + return cstrust.TLSCertificateLoader{ + SignerGen: newCachingSignerGen(ia, extKeyUsage, db, cfgDir), + } +} + // NewSigner creates a renewing signer backed by a certificate chain. -func NewSigner(ia addr.IA, db trust.DB, cfgDir string) (cstrust.RenewingSigner, error) { +func NewSigner(ia addr.IA, db trust.DB, cfgDir string) cstrust.RenewingSigner { + signer := cstrust.RenewingSigner{ + SignerGen: newCachingSignerGen(ia, x509.ExtKeyUsageAny, db, cfgDir), + } + + ctx, cancelF := context.WithTimeout(context.Background(), time.Second) + defer cancelF() + if _, err := signer.SignerGen.Generate(ctx); err != nil { + log.Debug("Initial signer generation failed", "err", err) + } + return signer +} + +// newCachingSignerGen creates a caching signer generator (i.e. a key/cert loader). +// If key usage is specified (not ExtKeyUsageAny), only signers with matching +// certificates will be returned. +func newCachingSignerGen( + ia addr.IA, + extKeyUsage x509.ExtKeyUsage, + db trust.DB, + cfgDir string, +) *cstrust.CachingSignerGen { + gen := trust.SignerGen{ IA: ia, DB: cstrust.CryptoLoader{ @@ -76,20 +111,12 @@ func NewSigner(ia addr.IA, db trust.DB, cfgDir string) (cstrust.RenewingSigner, KeyRing: cstrust.LoadingRing{ Dir: filepath.Join(cfgDir, "crypto/as"), }, + ExtKeyUsage: extKeyUsage, } - signer := cstrust.RenewingSigner{ - SignerGen: &cstrust.CachingSignerGen{ - SignerGen: gen, - Interval: 5 * time.Second, - }, - } - - ctx, cancelF := context.WithTimeout(context.Background(), time.Second) - defer cancelF() - if _, err := signer.SignerGen.Generate(ctx); err != nil { - log.Debug("Initial signer generation failed", "err", err) + return &cstrust.CachingSignerGen{ + SignerGen: gen, + Interval: 5 * time.Second, } - return signer, nil } type ChainBuilderConfig struct { diff --git a/control/trust/BUILD.bazel b/control/trust/BUILD.bazel index 5a4e62547..f0595b9e2 100644 --- a/control/trust/BUILD.bazel +++ b/control/trust/BUILD.bazel @@ -7,6 +7,7 @@ go_library( "key_loader.go", "signer.go", "signer_gen.go", + "tls_loader.go", ], importpath = "github.com/scionproto/scion/control/trust", visibility = ["//visibility:public"], diff --git a/control/trust/signer_gen_test.go b/control/trust/signer_gen_test.go index 70d7c14ae..de65a7eee 100644 --- a/control/trust/signer_gen_test.go +++ b/control/trust/signer_gen_test.go @@ -22,10 +22,10 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" - "github.com/scionproto/scion/control/trust" + cstrust "github.com/scionproto/scion/control/trust" "github.com/scionproto/scion/control/trust/mock_trust" "github.com/scionproto/scion/pkg/private/serrors" - libtrust "github.com/scionproto/scion/private/trust" + "github.com/scionproto/scion/private/trust" ) func TestChachingSignerGen(t *testing.T) { @@ -34,90 +34,90 @@ func TestChachingSignerGen(t *testing.T) { testCases := map[string]struct { Interval time.Duration - SignerGen func(mctrl *gomock.Controller) trust.SignerGen + SignerGen func(mctrl *gomock.Controller) cstrust.SignerGen FirstErr assert.ErrorAssertionFunc - FirstSigner libtrust.Signer + FirstSigner trust.Signer SecondErr assert.ErrorAssertionFunc - SecondSigner libtrust.Signer + SecondSigner trust.Signer }{ "valid": { Interval: time.Hour, - SignerGen: func(mctrl *gomock.Controller) trust.SignerGen { + SignerGen: func(mctrl *gomock.Controller) cstrust.SignerGen { gen := mock_trust.NewMockSignerGen(mctrl) gen.EXPECT().Generate(gomock.Any()).Return( - libtrust.Signer{Expiration: exp}, nil, + trust.Signer{Expiration: exp}, nil, ) return gen }, FirstErr: assert.NoError, - FirstSigner: libtrust.Signer{Expiration: exp}, + FirstSigner: trust.Signer{Expiration: exp}, SecondErr: assert.NoError, - SecondSigner: libtrust.Signer{Expiration: exp}, + SecondSigner: trust.Signer{Expiration: exp}, }, "valid, regenerate after interval": { Interval: 0, - SignerGen: func(mctrl *gomock.Controller) trust.SignerGen { + SignerGen: func(mctrl *gomock.Controller) cstrust.SignerGen { gen := mock_trust.NewMockSignerGen(mctrl) gen.EXPECT().Generate(gomock.Any()).Return( - libtrust.Signer{Expiration: exp}, nil, + trust.Signer{Expiration: exp}, nil, ) gen.EXPECT().Generate(gomock.Any()).Return( - libtrust.Signer{Expiration: otherExp}, nil, + trust.Signer{Expiration: otherExp}, nil, ) return gen }, FirstErr: assert.NoError, - FirstSigner: libtrust.Signer{Expiration: exp}, + FirstSigner: trust.Signer{Expiration: exp}, SecondErr: assert.NoError, - SecondSigner: libtrust.Signer{Expiration: otherExp}, + SecondSigner: trust.Signer{Expiration: otherExp}, }, "first fails, second cached": { Interval: time.Hour, - SignerGen: func(mctrl *gomock.Controller) trust.SignerGen { + SignerGen: func(mctrl *gomock.Controller) cstrust.SignerGen { gen := mock_trust.NewMockSignerGen(mctrl) gen.EXPECT().Generate(gomock.Any()).Return( - libtrust.Signer{}, serrors.New("internal"), + trust.Signer{}, serrors.New("internal"), ) return gen }, FirstErr: assert.Error, - FirstSigner: libtrust.Signer{}, + FirstSigner: trust.Signer{}, SecondErr: assert.Error, - SecondSigner: libtrust.Signer{}, + SecondSigner: trust.Signer{}, }, "first fails, second succeeds": { Interval: 0, - SignerGen: func(mctrl *gomock.Controller) trust.SignerGen { + SignerGen: func(mctrl *gomock.Controller) cstrust.SignerGen { gen := mock_trust.NewMockSignerGen(mctrl) gen.EXPECT().Generate(gomock.Any()).Return( - libtrust.Signer{}, serrors.New("internal"), + trust.Signer{}, serrors.New("internal"), ) gen.EXPECT().Generate(gomock.Any()).Return( - libtrust.Signer{Expiration: exp}, nil, + trust.Signer{Expiration: exp}, nil, ) return gen }, FirstErr: assert.Error, - FirstSigner: libtrust.Signer{}, + FirstSigner: trust.Signer{}, SecondErr: assert.NoError, - SecondSigner: libtrust.Signer{Expiration: exp}, + SecondSigner: trust.Signer{Expiration: exp}, }, "second fails, serve cached": { Interval: 0, - SignerGen: func(mctrl *gomock.Controller) trust.SignerGen { + SignerGen: func(mctrl *gomock.Controller) cstrust.SignerGen { gen := mock_trust.NewMockSignerGen(mctrl) gen.EXPECT().Generate(gomock.Any()).Return( - libtrust.Signer{Expiration: exp}, nil, + trust.Signer{Expiration: exp}, nil, ) gen.EXPECT().Generate(gomock.Any()).Return( - libtrust.Signer{}, serrors.New("internal"), + trust.Signer{}, serrors.New("internal"), ) return gen }, FirstErr: assert.NoError, - FirstSigner: libtrust.Signer{Expiration: exp}, + FirstSigner: trust.Signer{Expiration: exp}, SecondErr: assert.NoError, - SecondSigner: libtrust.Signer{Expiration: exp}, + SecondSigner: trust.Signer{Expiration: exp}, }, } for name, tc := range testCases { @@ -125,7 +125,7 @@ func TestChachingSignerGen(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() mctrl := gomock.NewController(t) - gen := trust.CachingSignerGen{ + gen := cstrust.CachingSignerGen{ SignerGen: tc.SignerGen(mctrl), Interval: tc.Interval, } diff --git a/control/trust/tls_loader.go b/control/trust/tls_loader.go new file mode 100644 index 000000000..c75ebdda6 --- /dev/null +++ b/control/trust/tls_loader.go @@ -0,0 +1,70 @@ +// Copyright 2022 ETH Zurich +// +// 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 trust + +import ( + "context" + "crypto/tls" + + "github.com/scionproto/scion/private/trust" +) + +// TLSCertificateLoader is a wrapper for a SignerGen, converting the +// trust.Signer to an equivalent tls.Certificate. +type TLSCertificateLoader struct { + SignerGen SignerGen +} + +// GetCertificate returns the certificate representing the Signer generated by +// the SignerGen. +// This function can be bound to tls.Config.GetCertificate. +func (l TLSCertificateLoader) GetCertificate( + hello *tls.ClientHelloInfo, +) (*tls.Certificate, error) { + + return l.Get(hello.Context()) +} + +// GetClientCertificate returns the certificate representing the Signer +// generated by the SignerGen. +// This function can be bound to tls.Config.GetClientCertificate. +func (l TLSCertificateLoader) GetClientCertificate( + reqInfo *tls.CertificateRequestInfo, +) (*tls.Certificate, error) { + + return l.Get(reqInfo.Context()) +} + +// Get returns the certificate representing the Signer +// generated by the SignerGen. +func (l TLSCertificateLoader) Get(ctx context.Context) (*tls.Certificate, error) { + signer, err := l.SignerGen.Generate(ctx) + if err != nil { + return nil, err + } + return toTLSCertificate(signer), nil +} + +func toTLSCertificate(signer trust.Signer) *tls.Certificate { + certificate := make([][]byte, len(signer.Chain)) + for i := range signer.Chain { + certificate[i] = signer.Chain[i].Raw + } + return &tls.Certificate{ + Certificate: certificate, + PrivateKey: signer.PrivateKey, + Leaf: signer.Chain[0], + } +} diff --git a/control/trust_test.go b/control/trust_test.go index aa4637c8d..1d951225e 100644 --- a/control/trust_test.go +++ b/control/trust_test.go @@ -35,12 +35,11 @@ func TestNewSigner(t *testing.T) { db, err := sqlite.New("file::memory:") require.NoError(t, err) - signer, err := cs.NewSigner( + signer := cs.NewSigner( xtest.MustParseIA("1-ff00:0:110"), db, filepath.Join(dir, "/ISD1/ASff00_0_110"), ) - require.NoError(t, err) _, err = signer.Sign(context.Background(), []byte("message")) require.NoError(t, err) diff --git a/private/app/appnet/infraenv.go b/private/app/appnet/infraenv.go index 6f00a6d2b..7f4acdab2 100644 --- a/private/app/appnet/infraenv.go +++ b/private/app/appnet/infraenv.go @@ -48,8 +48,11 @@ import ( // QUIC contains the QUIC configuration for control-plane speakers. type QUIC struct { // Address is the UDP address to start the QUIC server on. - Address string - TLSManager *trust.TLSCryptoManager + Address string + + GetCertificate func(*tls.ClientHelloInfo) (*tls.Certificate, error) + GetClientCertificate func(*tls.CertificateRequestInfo) (*tls.Certificate, error) + TLSVerifier *trust.TLSCryptoVerifier } // NetworkConfig describes the networking configuration of a SCION @@ -108,10 +111,9 @@ func (nc *NetworkConfig) QUICStack() (*QUICStack, error) { log.Info("QUIC server conn initialized", "local_addr", server.LocalAddr()) log.Info("QUIC client conn initialized", "local_addr", client.LocalAddr()) - tlsMgr := nc.QUIC.TLSManager serverTLSConfig := &tls.Config{ InsecureSkipVerify: true, - GetCertificate: tlsMgr.GetCertificate, + GetCertificate: nc.QUIC.GetCertificate, ClientAuth: tls.RequestClientCert, NextProtos: []string{"SCION"}, } @@ -139,9 +141,9 @@ func (nc *NetworkConfig) QUICStack() (*QUICStack, error) { } clientTLSConfig := &tls.Config{ InsecureSkipVerify: true, // ... but VerifyServerCertificate and VerifyConnection - GetClientCertificate: tlsMgr.GetClientCertificate, - VerifyPeerCertificate: tlsMgr.VerifyServerCertificate, - VerifyConnection: tlsMgr.VerifyConnection, + GetClientCertificate: nc.QUIC.GetClientCertificate, + VerifyPeerCertificate: nc.QUIC.TLSVerifier.VerifyServerCertificate, + VerifyConnection: nc.QUIC.TLSVerifier.VerifyConnection, NextProtos: []string{"SCION"}, } diff --git a/private/trust/BUILD.bazel b/private/trust/BUILD.bazel index f10d1e691..7c688b352 100644 --- a/private/trust/BUILD.bazel +++ b/private/trust/BUILD.bazel @@ -15,9 +15,8 @@ go_library( "signer.go", "signer_gen.go", "store.go", - "tls_handshake.go", + "tls_verifier.go", "verifier.go", - "x509_provider.go", ], importpath = "github.com/scionproto/scion/private/trust", visibility = ["//visibility:public"], @@ -58,10 +57,9 @@ go_test( "signer_gen_test.go", "signer_test.go", "store_test.go", - "tls_handshake_test.go", + "tls_verifier_test.go", "verifier_bench_test.go", "verifier_test.go", - "x509_provider_test.go", ], data = glob(["testdata/**"]), embed = [":go_default_library"], diff --git a/private/trust/mock_trust/BUILD.bazel b/private/trust/mock_trust/BUILD.bazel index f4687dcb2..c60a348c6 100644 --- a/private/trust/mock_trust/BUILD.bazel +++ b/private/trust/mock_trust/BUILD.bazel @@ -12,7 +12,6 @@ gomock( "Provider", "Recurser", "Router", - "X509KeyPairLoader", ], library = "//private/trust:go_default_library", package = "mock_trust", diff --git a/private/trust/mock_trust/mock.go b/private/trust/mock_trust/mock.go index 8a2d434c2..121aab5a2 100644 --- a/private/trust/mock_trust/mock.go +++ b/private/trust/mock_trust/mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/scionproto/scion/private/trust (interfaces: DB,Fetcher,Inspector,KeyRing,Provider,Recurser,Router,X509KeyPairLoader) +// Source: github.com/scionproto/scion/private/trust (interfaces: DB,Fetcher,Inspector,KeyRing,Provider,Recurser,Router) // Package mock_trust is a generated GoMock package. package mock_trust @@ -7,7 +7,6 @@ package mock_trust import ( context "context" crypto "crypto" - tls "crypto/tls" x509 "crypto/x509" net "net" reflect "reflect" @@ -401,56 +400,3 @@ func (mr *MockRouterMockRecorder) ChooseServer(arg0, arg1 interface{}) *gomock.C mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChooseServer", reflect.TypeOf((*MockRouter)(nil).ChooseServer), arg0, arg1) } - -// MockX509KeyPairLoader is a mock of X509KeyPairLoader interface. -type MockX509KeyPairLoader struct { - ctrl *gomock.Controller - recorder *MockX509KeyPairLoaderMockRecorder -} - -// MockX509KeyPairLoaderMockRecorder is the mock recorder for MockX509KeyPairLoader. -type MockX509KeyPairLoaderMockRecorder struct { - mock *MockX509KeyPairLoader -} - -// NewMockX509KeyPairLoader creates a new mock instance. -func NewMockX509KeyPairLoader(ctrl *gomock.Controller) *MockX509KeyPairLoader { - mock := &MockX509KeyPairLoader{ctrl: ctrl} - mock.recorder = &MockX509KeyPairLoaderMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockX509KeyPairLoader) EXPECT() *MockX509KeyPairLoaderMockRecorder { - return m.recorder -} - -// LoadClientKeyPair mocks base method. -func (m *MockX509KeyPairLoader) LoadClientKeyPair(arg0 context.Context) (*tls.Certificate, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadClientKeyPair", arg0) - ret0, _ := ret[0].(*tls.Certificate) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// LoadClientKeyPair indicates an expected call of LoadClientKeyPair. -func (mr *MockX509KeyPairLoaderMockRecorder) LoadClientKeyPair(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadClientKeyPair", reflect.TypeOf((*MockX509KeyPairLoader)(nil).LoadClientKeyPair), arg0) -} - -// LoadServerKeyPair mocks base method. -func (m *MockX509KeyPairLoader) LoadServerKeyPair(arg0 context.Context) (*tls.Certificate, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadServerKeyPair", arg0) - ret0, _ := ret[0].(*tls.Certificate) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// LoadServerKeyPair indicates an expected call of LoadServerKeyPair. -func (mr *MockX509KeyPairLoaderMockRecorder) LoadServerKeyPair(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadServerKeyPair", reflect.TypeOf((*MockX509KeyPairLoader)(nil).LoadServerKeyPair), arg0) -} diff --git a/private/trust/signer_gen.go b/private/trust/signer_gen.go index d7a583b60..5196d1fca 100644 --- a/private/trust/signer_gen.go +++ b/private/trust/signer_gen.go @@ -37,6 +37,11 @@ type SignerGen struct { IA addr.IA KeyRing KeyRing DB DB // FIXME(roosd): Eventually this should use a crypto provider + + // ExtKeyUsage filters the available certificates for specific key usage types. + // If ExtKeyUsage is not ExtKeyUsageAny, Generate will return a Signer with + // a certificate supporting this usage type (if one exists). + ExtKeyUsage x509.ExtKeyUsage } // Generate fetches private keys from the key ring and searches active @@ -109,6 +114,9 @@ func (s *SignerGen) bestForKey(ctx context.Context, key crypto.Signer, // TODO metrics.Signer.Generate(l.WithResult(metrics.ErrDB)).Inc() return nil, err } + if s.ExtKeyUsage != x509.ExtKeyUsageAny { + chains = filterChains(chains, s.ExtKeyUsage) + } chain := bestChain(&trcs[0].TRC, chains) if chain == nil && len(trcs) == 1 { return nil, nil @@ -144,6 +152,18 @@ func (s *SignerGen) bestForKey(ctx context.Context, key crypto.Signer, }, nil } +// filterChains returns only the chains with matching key usage. +func filterChains(chains [][]*x509.Certificate, keyUsage x509.ExtKeyUsage) [][]*x509.Certificate { + filtered := make([][]*x509.Certificate, 0, len(chains)) + for _, chain := range chains { + if err := verifyExtendedKeyUsage(chain[0], keyUsage); err != nil { + continue + } + filtered = append(filtered, chain) + } + return filtered +} + func bestChain(trc *cppki.TRC, chains [][]*x509.Certificate) []*x509.Certificate { opts := cppki.VerifyOptions{TRC: []*cppki.TRC{trc}} var best []*x509.Certificate diff --git a/private/trust/tls_handshake.go b/private/trust/tls_verifier.go similarity index 65% rename from private/trust/tls_handshake.go rename to private/trust/tls_verifier.go index 809881e59..241e9edc3 100644 --- a/private/trust/tls_handshake.go +++ b/private/trust/tls_verifier.go @@ -28,86 +28,54 @@ import ( const defaultTimeout = 5 * time.Second -type X509KeyPairLoader interface { - // LoadServerKeyPair provides a certificate to be presented by the server - // during TLS handshake. - LoadServerKeyPair(ctx context.Context) (*tls.Certificate, error) - // LoadClientKeyPair provides a certificate to be presented by the client - // during TLS handshake. - LoadClientKeyPair(ctx context.Context) (*tls.Certificate, error) -} - -// TLSCryptoManager implements callbacks which will be called during TLS handshake. -type TLSCryptoManager struct { - Loader X509KeyPairLoader +// TLSCryptoVerifier implements callbacks which will be called during TLS handshake. +type TLSCryptoVerifier struct { DB DB Timeout time.Duration } -// NewTLSCryptoManager returns a new instance with the defaultTimeout. -func NewTLSCryptoManager(loader X509KeyPairLoader, db DB) *TLSCryptoManager { - return &TLSCryptoManager{ +// NewTLSCryptoVerifier returns a new instance with the defaultTimeout. +func NewTLSCryptoVerifier(db DB) *TLSCryptoVerifier { + return &TLSCryptoVerifier{ DB: db, - Loader: loader, Timeout: defaultTimeout, } } -// GetCertificate retrieves a certificate to be presented during TLS handshake. -func (m *TLSCryptoManager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { - c, err := m.Loader.LoadServerKeyPair(hello.Context()) - if err != nil { - return nil, serrors.WrapStr("loading server key pair", err) - } - return c, nil -} - -// GetClientCertificate retrieves a client certificate to be presented during TLS handshake. -func (m *TLSCryptoManager) GetClientCertificate( - reqInfo *tls.CertificateRequestInfo, -) (*tls.Certificate, error) { - - c, err := m.Loader.LoadClientKeyPair(reqInfo.Context()) - if err != nil { - return nil, serrors.WrapStr("loading client key pair", err) - } - return c, nil -} - // VerifyServerCertificate verifies the certificate presented by the server // using the CP-PKI. -func (m *TLSCryptoManager) VerifyServerCertificate( +func (v *TLSCryptoVerifier) VerifyServerCertificate( rawCerts [][]byte, _ [][]*x509.Certificate, ) error { - return m.verifyRawPeerCertificate(rawCerts, x509.ExtKeyUsageServerAuth) + return v.verifyRawPeerCertificate(rawCerts, x509.ExtKeyUsageServerAuth) } // VerifyClientCertificate verifies the certificate presented by the client // using the CP-PKI. -func (m *TLSCryptoManager) VerifyClientCertificate( +func (v *TLSCryptoVerifier) VerifyClientCertificate( rawCerts [][]byte, _ [][]*x509.Certificate, ) error { - return m.verifyRawPeerCertificate(rawCerts, x509.ExtKeyUsageClientAuth) + return v.verifyRawPeerCertificate(rawCerts, x509.ExtKeyUsageClientAuth) } // VerifyParsedClientCertificate verifies the certificate presented by the // client using the CP-PKI. // If the certificate is valid, returns the subject IA. -func (m *TLSCryptoManager) VerifyParsedClientCertificate( +func (v *TLSCryptoVerifier) VerifyParsedClientCertificate( chain []*x509.Certificate, ) (addr.IA, error) { - return m.verifyParsedPeerCertificate(chain, x509.ExtKeyUsageClientAuth) + return v.verifyParsedPeerCertificate(chain, x509.ExtKeyUsageClientAuth) } // VerifyConnection callback is intended to be used by the client to verify // that the certificate presented by the server matches the server name // the client is trying to connect to. -func (m *TLSCryptoManager) VerifyConnection(cs tls.ConnectionState) error { +func (v *TLSCryptoVerifier) VerifyConnection(cs tls.ConnectionState) error { serverNameIA := strings.Split(cs.ServerName, ",")[0] serverIA, err := addr.ParseIA(serverNameIA) if err != nil { @@ -126,7 +94,7 @@ func (m *TLSCryptoManager) VerifyConnection(cs tls.ConnectionState) error { // verifyRawPeerCertificate verifies the certificate presented by the peer during TLS handshake, // based on the TRC. -func (m *TLSCryptoManager) verifyRawPeerCertificate( +func (v *TLSCryptoVerifier) verifyRawPeerCertificate( rawCerts [][]byte, extKeyUsage x509.ExtKeyUsage, ) error { @@ -139,13 +107,13 @@ func (m *TLSCryptoManager) verifyRawPeerCertificate( } chain[i] = cert } - _, err := m.verifyParsedPeerCertificate(chain, extKeyUsage) + _, err := v.verifyParsedPeerCertificate(chain, extKeyUsage) return err } // verifyParsedPeerCertificate verifies the certificate presented by the peer during TLS handshake, // based on the TRC. -func (m *TLSCryptoManager) verifyParsedPeerCertificate( +func (v *TLSCryptoVerifier) verifyParsedPeerCertificate( chain []*x509.Certificate, extKeyUsage x509.ExtKeyUsage, ) (addr.IA, error) { @@ -160,9 +128,9 @@ func (m *TLSCryptoManager) verifyParsedPeerCertificate( if err != nil { return 0, serrors.WrapStr("extracting ISD-AS from peer certificate", err) } - ctx, cancel := context.WithTimeout(context.Background(), m.Timeout) + ctx, cancel := context.WithTimeout(context.Background(), v.Timeout) defer cancel() - trcs, _, err := activeTRCs(ctx, m.DB, ia.ISD()) + trcs, _, err := activeTRCs(ctx, v.DB, ia.ISD()) if err != nil { return 0, serrors.WrapStr("loading TRCs", err) } diff --git a/private/trust/tls_handshake_test.go b/private/trust/tls_verifier_test.go similarity index 84% rename from private/trust/tls_handshake_test.go rename to private/trust/tls_verifier_test.go index bba085b56..6849b74c6 100644 --- a/private/trust/tls_handshake_test.go +++ b/private/trust/tls_verifier_test.go @@ -32,7 +32,7 @@ import ( "github.com/scionproto/scion/private/trust/mock_trust" ) -func TestTLSCryptoManagerVerifyServerCertificate(t *testing.T) { +func TestTLSCryptoVerifierVerifyServerCertificate(t *testing.T) { dir := genCrypto(t) trc := xtest.LoadTRC(t, filepath.Join(dir, "trcs/ISD1-B1-S1.trc")) @@ -61,18 +61,18 @@ func TestTLSCryptoManagerVerifyServerCertificate(t *testing.T) { defer ctrl.Finish() db := tc.db(ctrl) - mgr := trust.TLSCryptoManager{ + verifier := trust.TLSCryptoVerifier{ DB: db, Timeout: 5 * time.Second, } rawChain := loadRawChain(t, crt111File) - err := mgr.VerifyServerCertificate(rawChain, nil) + err := verifier.VerifyServerCertificate(rawChain, nil) tc.assertErr(t, err) }) } } -func TestTLSCryptoManagerVerifyClientCertificate(t *testing.T) { +func TestTLSCryptoVerifierVerifyClientCertificate(t *testing.T) { dir := genCrypto(t) trc := xtest.LoadTRC(t, filepath.Join(dir, "trcs/ISD1-B1-S1.trc")) @@ -101,12 +101,12 @@ func TestTLSCryptoManagerVerifyClientCertificate(t *testing.T) { defer ctrl.Finish() db := tc.db(ctrl) - mgr := trust.TLSCryptoManager{ + verifier := trust.TLSCryptoVerifier{ DB: db, Timeout: 5 * time.Second, } rawChain := loadRawChain(t, crt111File) - err := mgr.VerifyClientCertificate(rawChain, nil) + err := verifier.VerifyClientCertificate(rawChain, nil) tc.assertErr(t, err) }) } @@ -130,24 +130,25 @@ func TestHandshake(t *testing.T) { db := mock_trust.NewMockDB(ctrl) db.EXPECT().SignedTRC(gomock.Any(), gomock.Any()).MaxTimes(2).Return(trc, nil) - loader := mock_trust.NewMockX509KeyPairLoader(ctrl) - loader.EXPECT().LoadServerKeyPair(gomock.Any()).Return(&tlsCert, nil) - loader.EXPECT().LoadClientKeyPair(gomock.Any()).Return(&tlsCert, nil) - mgr := trust.NewTLSCryptoManager(loader, db) + verifier := trust.NewTLSCryptoVerifier(db) clientConn, serverConn := net.Pipe() defer clientConn.Close() defer serverConn.Close() client := tls.Client(clientConn, &tls.Config{ - InsecureSkipVerify: true, - GetClientCertificate: mgr.GetClientCertificate, - VerifyPeerCertificate: mgr.VerifyServerCertificate, + InsecureSkipVerify: true, + GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) { + return &tlsCert, nil + }, + VerifyPeerCertificate: verifier.VerifyServerCertificate, }) server := tls.Server(serverConn, &tls.Config{ - InsecureSkipVerify: true, - GetCertificate: mgr.GetCertificate, - VerifyPeerCertificate: mgr.VerifyClientCertificate, + InsecureSkipVerify: true, + GetCertificate: func(*tls.ClientHelloInfo) (*tls.Certificate, error) { + return &tlsCert, nil + }, + VerifyPeerCertificate: verifier.VerifyClientCertificate, ClientAuth: tls.RequireAnyClientCert, }) diff --git a/private/trust/x509_provider.go b/private/trust/x509_provider.go deleted file mode 100644 index 0313d51fa..000000000 --- a/private/trust/x509_provider.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2022 ETH Zurich -// -// 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 trust - -import ( - "context" - "crypto" - "crypto/tls" - "crypto/x509" - "time" - - "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/private/serrors" - "github.com/scionproto/scion/pkg/scrypto/cppki" -) - -// X509KeyPairProvider loads x509 certificate/key pairs -// from the trust DB. -type X509KeyPairProvider struct { - IA addr.IA - DB DB - KeyLoader KeyRing -} - -var _ X509KeyPairLoader = (*X509KeyPairProvider)(nil) - -// LoadServerKeyPair loads a valid tls.Certificate with id-kp-serverAuth. -// See: https://docs.scion.org/en/latest/cryptography/certificates.html#extended-key-usage-extension -func (p X509KeyPairProvider) LoadServerKeyPair(ctx context.Context) (*tls.Certificate, error) { - return p.loadX509KeyPair(ctx, x509.ExtKeyUsageServerAuth) -} - -// LoadClientKeyPair loads a valid tls.Certificate with id-kp-clientAuth. -// See: https://docs.scion.org/en/latest/cryptography/certificates.html#extended-key-usage-extension -func (p X509KeyPairProvider) LoadClientKeyPair(ctx context.Context) (*tls.Certificate, error) { - return p.loadX509KeyPair(ctx, x509.ExtKeyUsageServerAuth) -} - -func (p X509KeyPairProvider) loadX509KeyPair( - ctx context.Context, - extKeyUsage x509.ExtKeyUsage, -) (*tls.Certificate, error) { - - keys, err := p.KeyLoader.PrivateKeys(ctx) - if err != nil { - return nil, serrors.WrapStr("getting keys", err) - } - if len(keys) == 0 { - return nil, serrors.New("no private key found") - } - - trcs, _, err := activeTRCs(ctx, p.DB, p.IA.ISD()) - if err != nil { - return nil, serrors.WrapStr("loading TRCs", err) - } - - var bestChain []*x509.Certificate - var bestKey crypto.Signer - var bestExpiry time.Time - for _, key := range keys { - cert, expiry, err := p.bestKeyPair(ctx, trcs, extKeyUsage, key) - if err != nil { - return nil, serrors.WrapStr("getting best key pair", err) - } - if cert == nil { - continue - } - if bestChain != nil && bestExpiry.After(expiry) { - continue - } - bestChain = cert - bestKey = key - bestExpiry = expiry - } - if bestChain == nil { - return nil, serrors.New("no certificate found") - } - certificate := make([][]byte, len(bestChain)) - for i := range bestChain { - certificate[i] = bestChain[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: bestKey, - Leaf: bestChain[0], - }, nil -} - -func (p X509KeyPairProvider) bestKeyPair( - ctx context.Context, - signedTRCs []cppki.SignedTRC, - extKeyUsage x509.ExtKeyUsage, - signer crypto.Signer, -) ([]*x509.Certificate, time.Time, error) { - - skid, err := cppki.SubjectKeyID(signer.Public()) - if err != nil { - return nil, time.Time{}, err - } - chains, err := p.DB.Chains(ctx, ChainQuery{ - IA: p.IA, - SubjectKeyID: skid, - Date: time.Now(), - }) - if err != nil { - return nil, time.Time{}, err - } - trcs := make([]*cppki.TRC, len(signedTRCs)) - for i, signedTRC := range signedTRCs { - signedTRC := signedTRC - trcs[i] = &signedTRC.TRC - } - chain := bestChainWithKeyUsage(trcs, chains, extKeyUsage) - if chain == nil { - return nil, time.Time{}, nil - } - return chain, chain[0].NotAfter, nil -} - -func bestChainWithKeyUsage( - trcs []*cppki.TRC, - chains [][]*x509.Certificate, - extKeyUsage x509.ExtKeyUsage, -) []*x509.Certificate { - - opts := cppki.VerifyOptions{TRC: trcs} - var best []*x509.Certificate - for _, chain := range chains { - if err := verifyExtendedKeyUsage(chain[0], extKeyUsage); err != nil { - continue - } - if err := cppki.VerifyChain(chain, opts); err != nil { - continue - } - // Use the chain if its validity is longer than any other found so far. - if len(best) == 0 || chain[0].NotAfter.After(best[0].NotAfter) { - best = chain - } - } - return best -} diff --git a/private/trust/x509_provider_test.go b/private/trust/x509_provider_test.go deleted file mode 100644 index 375284d4e..000000000 --- a/private/trust/x509_provider_test.go +++ /dev/null @@ -1,926 +0,0 @@ -// Copyright 2022 ETH Zurich -// -// 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 trust_test - -import ( - "bytes" - "context" - "crypto" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "crypto/tls" - "crypto/x509" - "encoding/pem" - "os" - "path/filepath" - "testing" - "time" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/pkg/private/serrors" - "github.com/scionproto/scion/pkg/private/xtest" - "github.com/scionproto/scion/pkg/scrypto/cppki" - "github.com/scionproto/scion/private/trust" - "github.com/scionproto/scion/private/trust/mock_trust" -) - -func TestLoadServerKeyPair(t *testing.T) { - dir := genCrypto(t) - - trc := xtest.LoadTRC(t, filepath.Join(dir, "trcs/ISD1-B1-S1.trc")) - key := loadSigner(t, filepath.Join(dir, "ISD1/ASff00_0_110/crypto/as/cp-as.key")) - - chain := getChain(t, dir) - longer := getChain(t, dir) - longer[0].NotAfter = longer[0].NotAfter.Add(time.Hour) - longer[0].SubjectKeyId = []byte("longer") - - shorter := getChain(t, dir) - shorter[0].NotAfter = shorter[0].NotAfter.Add(-time.Hour) - shorter[0].SubjectKeyId = []byte("shorter") - - longestKey := loadSigner(t, filepath.Join(dir, "ISD1/ASff00_0_111/crypto/as/cp-as.key")) - longestChain := xtest.LoadChain(t, - filepath.Join(dir, "ISD1/ASff00_0_111/crypto/as/ISD1-ASff00_0_111.pem")) - longestChain[0].NotAfter = longestChain[0].NotAfter.Add(2 * time.Hour) - longestChain[0].SubjectKeyId = []byte("longest") - - testCases := map[string]struct { - keyLoader func(mctrcl *gomock.Controller) trust.KeyRing - db func(mctrcl *gomock.Controller) trust.DB - assertFunc assert.ErrorAssertionFunc - expectedCert func() *tls.Certificate - }{ - "valid": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - cert := chain[0] - db := mock_trust.NewMockDB(mctrl) - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - [][]*x509.Certificate{chain}, nil, - ) - return db - }, - assertFunc: assert.NoError, - expectedCert: func() *tls.Certificate { - certificate := make([][]byte, len(chain)) - for i := range chain { - certificate[i] = chain[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: key, - Leaf: chain[0], - } - }, - }, - "newest": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - cert := chain[0] - db := mock_trust.NewMockDB(mctrl) - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - [][]*x509.Certificate{chain, longer, shorter}, nil, - ) - return db - }, - assertFunc: assert.NoError, - expectedCert: func() *tls.Certificate { - certificate := make([][]byte, len(longer)) - for i := range longer { - certificate[i] = longer[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: key, - Leaf: longer[0], - } - }, - }, - "newest multiple keys": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key, longestKey}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn( - func( - _ context.Context, - chainQuery trust.ChainQuery, - ) ([][]*x509.Certificate, error) { - skid, err := cppki.SubjectKeyID(longestKey.Public()) - if err != nil { - return nil, err - } - if bytes.Equal(chainQuery.SubjectKeyID, skid) { - return [][]*x509.Certificate{longestChain}, nil - } - return [][]*x509.Certificate{chain, longer, shorter}, nil - }, - ) - return db - }, - assertFunc: assert.NoError, - expectedCert: func() *tls.Certificate { - certificate := make([][]byte, len(longestChain)) - for i := range longer { - certificate[i] = longestChain[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: key, - Leaf: longestChain[0], - } - }, - }, - "select best from grace": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - cert := chain[0] - db := mock_trust.NewMockDB(mctrl) - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - - trc2 := xtest.LoadTRC(t, filepath.Join(dir, "ISD1/trcs/ISD1-B1-S1.trc")) - trc2.TRC.ID.Serial = 2 - trc2.TRC.Validity.NotBefore = time.Now() - trc2.TRC.GracePeriod = 5 * time.Minute - - roots, err := trc2.TRC.RootCerts() - require.NoError(t, err) - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - require.NoError(t, err) - for _, root := range roots { - root.PublicKey = key.Public() - } - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc2, nil, - ) - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1, Serial: 1, Base: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - [][]*x509.Certificate{chain, longer, shorter}, nil, - ) - return db - }, - assertFunc: assert.NoError, - expectedCert: func() *tls.Certificate { - certificate := make([][]byte, len(chain)) - for i := range chain { - certificate[i] = longer[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: key, - Leaf: longer[0], - } - }, - }, - "no keys": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - return mock_trust.NewMockDB(mctrl) - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "rsa key": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - - priv, err := rsa.GenerateKey(rand.Reader, 512) - require.NoError(t, err) - - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{priv}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "no chain found": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - cert := chain[0] - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - db.EXPECT().SignedTRC(ctxMatcher{}, - cppki.TRCID{ISD: 1}).Return(trc, nil) - db.EXPECT().Chains(gomock.Any(), matcher).Return(nil, nil) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "db.SignedTRC error": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - db.EXPECT().SignedTRC(ctxMatcher{}, - cppki.TRCID{ISD: 1}).Return( - cppki.SignedTRC{}, serrors.New("fail")) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "db.SignedTRC not found": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - cppki.SignedTRC{}, nil) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "db.Chain error": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - cert := chain[0] - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - db.EXPECT().SignedTRC(ctxMatcher{}, - cppki.TRCID{ISD: 1}).Return(trc, nil) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - nil, serrors.New("fail"), - ) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "correct EKU": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - invalidExtChain := getChain(t, dir) - invalidExtChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ - x509.ExtKeyUsageClientAuth, - x509.ExtKeyUsageTimeStamping, - } - validExtChain := getChain(t, dir) - validExtChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ - x509.ExtKeyUsageServerAuth, - x509.ExtKeyUsageTimeStamping, - } - cert := validExtChain[0] - db := mock_trust.NewMockDB(mctrl) - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - [][]*x509.Certificate{invalidExtChain, validExtChain}, nil, - ) - return db - }, - assertFunc: assert.NoError, - expectedCert: func() *tls.Certificate { - validExtChain := getChain(t, dir) - validExtChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ - x509.ExtKeyUsageServerAuth, - x509.ExtKeyUsageTimeStamping, - } - certificate := make([][]byte, len(validExtChain)) - for i := range validExtChain { - certificate[i] = validExtChain[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: key, - Leaf: validExtChain[0], - } - }, - }, - "wrong EKU": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - extChain := getChain(t, dir) - extChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ - x509.ExtKeyUsageClientAuth, - x509.ExtKeyUsageTimeStamping, - } - cert := extChain[0] - db := mock_trust.NewMockDB(mctrl) - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - [][]*x509.Certificate{extChain}, nil, - ) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - } - for name, tc := range testCases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - mctrl := gomock.NewController(t) - defer mctrl.Finish() - - provider := trust.X509KeyPairProvider{ - IA: xtest.MustParseIA("1-ff00:0:110"), - DB: tc.db(mctrl), - KeyLoader: tc.keyLoader(mctrl), - } - tlsCert, err := provider.LoadServerKeyPair(context.Background()) - tc.assertFunc(t, err) - if err == nil { - assert.Equal(t, tc.expectedCert().Leaf.SubjectKeyId, tlsCert.Leaf.SubjectKeyId) - } - }) - } -} - -func TestLoadClientKeyPair(t *testing.T) { - dir := genCrypto(t) - - trc := xtest.LoadTRC(t, filepath.Join(dir, "trcs/ISD1-B1-S1.trc")) - key := loadSigner(t, filepath.Join(dir, "ISD1/ASff00_0_110/crypto/as/cp-as.key")) - - chain := getChain(t, dir) - longer := getChain(t, dir) - longer[0].NotAfter = longer[0].NotAfter.Add(time.Hour) - longer[0].SubjectKeyId = []byte("longer") - - shorter := getChain(t, dir) - shorter[0].NotAfter = shorter[0].NotAfter.Add(-time.Hour) - shorter[0].SubjectKeyId = []byte("shorter") - - longestKey := loadSigner(t, filepath.Join(dir, "ISD1/ASff00_0_111/crypto/as/cp-as.key")) - longestChain := xtest.LoadChain(t, - filepath.Join(dir, "ISD1/ASff00_0_111/crypto/as/ISD1-ASff00_0_111.pem")) - longestChain[0].NotAfter = longestChain[0].NotAfter.Add(2 * time.Hour) - longestChain[0].SubjectKeyId = []byte("longest") - - testCases := map[string]struct { - keyLoader func(mctrcl *gomock.Controller) trust.KeyRing - db func(mctrcl *gomock.Controller) trust.DB - assertFunc assert.ErrorAssertionFunc - expectedCert func() *tls.Certificate - }{ - "valid": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - cert := chain[0] - db := mock_trust.NewMockDB(mctrl) - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - [][]*x509.Certificate{chain}, nil, - ) - return db - }, - assertFunc: assert.NoError, - expectedCert: func() *tls.Certificate { - certificate := make([][]byte, len(chain)) - for i := range chain { - certificate[i] = chain[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: key, - Leaf: chain[0], - } - }, - }, - "newest": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - cert := chain[0] - db := mock_trust.NewMockDB(mctrl) - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - [][]*x509.Certificate{chain, longer, shorter}, nil, - ) - return db - }, - assertFunc: assert.NoError, - expectedCert: func() *tls.Certificate { - certificate := make([][]byte, len(longer)) - for i := range longer { - certificate[i] = longer[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: key, - Leaf: longer[0], - } - }, - }, - "newest multiple keys": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key, longestKey}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn( - func( - _ context.Context, - chainQuery trust.ChainQuery, - ) ([][]*x509.Certificate, error) { - skid, err := cppki.SubjectKeyID(longestKey.Public()) - if err != nil { - return nil, err - } - if bytes.Equal(chainQuery.SubjectKeyID, skid) { - return [][]*x509.Certificate{longestChain}, nil - } - return [][]*x509.Certificate{chain, longer, shorter}, nil - }, - ) - return db - }, - assertFunc: assert.NoError, - expectedCert: func() *tls.Certificate { - certificate := make([][]byte, len(longestChain)) - for i := range longer { - certificate[i] = longestChain[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: key, - Leaf: longestChain[0], - } - }, - }, - "select best from grace": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - cert := chain[0] - db := mock_trust.NewMockDB(mctrl) - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - - trc2 := xtest.LoadTRC(t, filepath.Join(dir, "ISD1/trcs/ISD1-B1-S1.trc")) - trc2.TRC.ID.Serial = 2 - trc2.TRC.Validity.NotBefore = time.Now() - trc2.TRC.GracePeriod = 5 * time.Minute - - roots, err := trc2.TRC.RootCerts() - require.NoError(t, err) - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - require.NoError(t, err) - for _, root := range roots { - root.PublicKey = key.Public() - } - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc2, nil, - ) - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1, Serial: 1, Base: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - [][]*x509.Certificate{chain, longer, shorter}, nil, - ) - return db - }, - assertFunc: assert.NoError, - expectedCert: func() *tls.Certificate { - certificate := make([][]byte, len(chain)) - for i := range chain { - certificate[i] = longer[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: key, - Leaf: longer[0], - } - }, - }, - "no keys": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - return mock_trust.NewMockDB(mctrl) - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "rsa key": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - - priv, err := rsa.GenerateKey(rand.Reader, 512) - require.NoError(t, err) - - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{priv}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "no chain found": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - cert := chain[0] - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - db.EXPECT().SignedTRC(ctxMatcher{}, - cppki.TRCID{ISD: 1}).Return(trc, nil) - db.EXPECT().Chains(gomock.Any(), matcher).Return(nil, nil) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "db.SignedTRC error": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - db.EXPECT().SignedTRC(ctxMatcher{}, - cppki.TRCID{ISD: 1}).Return( - cppki.SignedTRC{}, serrors.New("fail")) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "db.SignedTRC not found": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - cppki.SignedTRC{}, nil) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "db.Chain error": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - db := mock_trust.NewMockDB(mctrl) - cert := chain[0] - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - db.EXPECT().SignedTRC(ctxMatcher{}, - cppki.TRCID{ISD: 1}).Return(trc, nil) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - nil, serrors.New("fail"), - ) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - "correct EKU": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - invalidExtChain := getChain(t, dir) - invalidExtChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ - x509.ExtKeyUsageClientAuth, - x509.ExtKeyUsageTimeStamping, - } - validExtChain := getChain(t, dir) - validExtChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ - x509.ExtKeyUsageServerAuth, - x509.ExtKeyUsageTimeStamping, - } - cert := validExtChain[0] - db := mock_trust.NewMockDB(mctrl) - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - [][]*x509.Certificate{invalidExtChain, validExtChain}, nil, - ) - return db - }, - assertFunc: assert.NoError, - expectedCert: func() *tls.Certificate { - validExtChain := getChain(t, dir) - validExtChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ - x509.ExtKeyUsageServerAuth, - x509.ExtKeyUsageTimeStamping, - } - certificate := make([][]byte, len(validExtChain)) - for i := range validExtChain { - certificate[i] = validExtChain[i].Raw - } - return &tls.Certificate{ - Certificate: certificate, - PrivateKey: key, - Leaf: validExtChain[0], - } - }, - }, - "wrong EKU": { - keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { - loader := mock_trust.NewMockKeyRing(mctrl) - loader.EXPECT().PrivateKeys(gomock.Any()).Return( - []crypto.Signer{key}, nil, - ) - return loader - }, - db: func(mctrl *gomock.Controller) trust.DB { - extChain := getChain(t, dir) - extChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ - x509.ExtKeyUsageClientAuth, - x509.ExtKeyUsageTimeStamping, - } - cert := extChain[0] - db := mock_trust.NewMockDB(mctrl) - matcher := chainQueryMatcher{ - ia: xtest.MustParseIA("1-ff00:0:110"), - skid: cert.SubjectKeyId, - } - db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( - trc, nil, - ) - db.EXPECT().Chains(gomock.Any(), matcher).Return( - [][]*x509.Certificate{extChain}, nil, - ) - return db - }, - assertFunc: assert.Error, - expectedCert: func() *tls.Certificate { - return nil - }, - }, - } - for name, tc := range testCases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - mctrl := gomock.NewController(t) - defer mctrl.Finish() - - provider := trust.X509KeyPairProvider{ - IA: xtest.MustParseIA("1-ff00:0:110"), - DB: tc.db(mctrl), - KeyLoader: tc.keyLoader(mctrl), - } - tlsCert, err := provider.LoadClientKeyPair(context.Background()) - tc.assertFunc(t, err) - if err == nil { - assert.Equal(t, tc.expectedCert().Leaf.SubjectKeyId, tlsCert.Leaf.SubjectKeyId) - } - }) - } -} -func getChain(t *testing.T, dir string) []*x509.Certificate { - return xtest.LoadChain(t, - filepath.Join(dir, "ISD1/ASff00_0_110/crypto/as/ISD1-ASff00_0_110.pem")) -} - -func loadSigner(t *testing.T, file string) crypto.Signer { - raw, err := os.ReadFile(file) - require.NoError(t, err) - block, _ := pem.Decode(raw) - if block == nil || block.Type != "PRIVATE KEY" { - panic("no valid private key block") - } - key, err := x509.ParsePKCS8PrivateKey(block.Bytes) - require.NoError(t, err) - return key.(crypto.Signer) -} From fc5c897fc640b6f769cbf2a44577265f717eafa6 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Fri, 10 Feb 2023 09:25:52 +0100 Subject: [PATCH 006/255] lint: fix errcheck violations (#4310) Remove (most) golangci-lint exceptions for the errcheck linter. This linter is generally very helpful and it seems better not to give blanket exceptions for violations. It's rarely necessary to use nolint to silence specific false positives, as it's usually enough to explicitly ignore errors by assigning to a blank identifier, which seems seems helpful for readers of the code. Fix errcheck violations: - Explicitly ignore or log errors where this seems appropriate - In http.Handler code, ignore errors when writing the response body. Use rw.Write where possible to make it as clear as possible that the Write is the only remaining possibility for errors. Some of the diagnostics pages would require more restructuring to handle errors properly; in some cases, errors are ignored by using fmt.Fprint (for which errcheck ignores errors), instead of Write. - Assert or panic on errors in tests - Remove some unused code snippets with violations (TestMain, log/testlog.SetupGlobals) - Restructure control/beacon.ParsePolicyYaml so initDefaults does not return an error (and btw, use correct input file in test) - Handle SetDeadline errors in sock/reliable/reconnect - Handle UnderlayPacket.DecodeFromBytes error in sock/reliable.Conn --- .golangcilint.yml | 80 +------------------ control/beacon/policy.go | 15 ++-- control/beacon/policy_test.go | 2 +- control/cmd/control/main.go | 8 +- .../reservation/conf/capacities_test.go | 2 +- control/colibri/reservation/segment/path.go | 2 +- control/mgmtapi/api.go | 7 +- dispatcher/cmd/dispatcher/main.go | 6 +- dispatcher/cmd/dispatcher/main_test.go | 5 -- dispatcher/dispatcher.go | 2 +- .../internal/registration/bench_test.go | 8 +- gateway/control/BUILD.bazel | 1 + gateway/control/aggregator.go | 2 +- gateway/control/engine.go | 32 ++++---- gateway/control/engine_test.go | 9 ++- gateway/control/enginecontroller_test.go | 10 ++- gateway/control/export_test.go | 17 ++-- gateway/control/remotemonitor.go | 4 +- gateway/control/router.go | 6 +- gateway/control/session.go | 4 +- gateway/control/sessionconfigurator.go | 6 +- gateway/control/watcher_test.go | 20 ++++- gateway/dataplane/diagnostics_test.go | 4 +- gateway/dataplane/ipforwarder_test.go | 10 +-- gateway/dataplane/routingtable.go | 2 +- gateway/dataplane/session_test.go | 15 ++-- gateway/gateway.go | 10 ++- gateway/routing/file.go | 3 +- gateway/xnet/xnet.go | 4 +- pkg/experimental/colibri/reservation/types.go | 12 +-- pkg/experimental/epic/epic_test.go | 9 ++- .../hiddenpath/beaconwriter_test.go | 4 +- .../hiddenpath/grpc/lookup_test.go | 10 ++- .../hiddenpath/grpc/registerer_test.go | 10 ++- .../hiddenpath/grpc/requester_test.go | 4 +- pkg/experimental/hiddenpath/store_test.go | 10 ++- pkg/grpc/BUILD.bazel | 1 + pkg/grpc/dialer_test.go | 11 ++- pkg/log/log.go | 11 +-- pkg/log/testlog/log.go | 5 -- pkg/private/xtest/BUILD.bazel | 2 + pkg/private/xtest/graph/BUILD.bazel | 1 + pkg/private/xtest/graph/graph.go | 5 +- pkg/private/xtest/grpc.go | 20 ++++- pkg/segment/seg.go | 1 + pkg/segment/segs_test.go | 3 +- pkg/slayers/extn_test.go | 3 +- pkg/slayers/scion_test.go | 31 ++++--- pkg/snet/packet_test.go | 2 +- pkg/snet/path.go | 10 ++- pkg/snet/squic/net.go | 8 +- pkg/sock/reliable/reconnect/conn.go | 26 +++--- pkg/sock/reliable/reliable.go | 13 ++- private/app/appnet/infraenv.go | 12 ++- private/app/launcher/launcher.go | 4 +- private/app/path/pathprobe/paths.go | 4 +- private/config/sample.go | 7 +- private/mgmtapi/cppki/api/api.go | 5 +- private/mgmtapi/segments/api/api.go | 5 +- private/path/combinator/combinator.go | 8 +- private/revcache/revcachetest/BUILD.bazel | 1 + private/revcache/revcachetest/revcachetest.go | 7 +- private/service/statuspages.go | 8 +- private/storage/trust/fspersister/db_test.go | 2 +- private/svc/internal/ctxconn/ctxconn.go | 4 +- private/trust/db_inspector.go | 2 +- private/trust/verifier.go | 2 +- private/trust/verifier_bench_test.go | 6 +- private/worker/BUILD.bazel | 1 + private/worker/worker_test.go | 15 ++-- router/bfd/BUILD.bazel | 1 - router/bfd/main_test.go | 30 ------- router/dataplane_test.go | 2 +- router/export_test.go | 4 +- router/mgmtapi/api.go | 2 +- scion-pki/trcs/combine_test.go | 2 +- tools/end2end/main.go | 8 +- tools/end2end_integration/main.go | 2 +- tools/integration/binary.go | 6 +- tools/integration/done.go | 4 +- tools/integration/integration.go | 3 +- tools/integration/progress/progress.go | 4 +- 82 files changed, 350 insertions(+), 319 deletions(-) delete mode 100644 router/bfd/main_test.go diff --git a/.golangcilint.yml b/.golangcilint.yml index 100bb83af..3bbbf5eaa 100644 --- a/.golangcilint.yml +++ b/.golangcilint.yml @@ -73,86 +73,14 @@ issues: - path: pkg/scrypto/cms linters: [goheader] - # list of exceptions to the errcheck check - # TODO(matzf): most of these should rather be fixed! It may be ok to be a - # bit more lenient in the test code perhaps, but some of these are lurking - # bugs. - - path: "^control/beacon/policy.go$|\ - ^control/cmd/control/main.go$|\ - ^control/colibri/reservation/conf/capacities_test.go$|\ - ^control/colibri/reservation/e2e/reservation_test.go$|\ + # Exceptions to errcheck for some experimental colibri code and some old-ish convey tests. + - linters: [errcheck] + path: "^control/colibri/reservation/e2e/reservation_test.go$|\ ^control/colibri/reservation/index_test.go$|\ ^control/colibri/reservation/reservationdbtest/reservationdbtest.go$|\ - ^control/colibri/reservation/segment/path.go$|\ ^control/colibri/reservation/segment/reservation_test.go$|\ ^control/colibri/reservation/sqlite/db_test.go$|\ ^control/colibri/reservationstore/store.go$|\ - ^control/mgmtapi/api.go$|\ - ^dispatcher/cmd/dispatcher/main.go$|\ - ^dispatcher/dispatcher.go$|\ - ^dispatcher/internal/registration/bench_test.go$|\ - ^gateway/control/aggregator.go$|\ - ^gateway/control/engine.go$|\ - ^gateway/control/engine_test.go$|\ - ^gateway/control/enginecontroller_test.go$|\ - ^gateway/control/export_test.go$|\ - ^gateway/control/remotemonitor.go$|\ - ^gateway/control/router.go$|\ - ^gateway/control/session.go$|\ - ^gateway/control/sessionconfigurator.go$|\ - ^gateway/control/watcher_test.go$|\ - ^gateway/dataplane/diagnostics_test.go$|\ - ^gateway/dataplane/ipforwarder_test.go$|\ - ^gateway/dataplane/routingtable.go$|\ - ^gateway/dataplane/session_test.go$|\ - ^gateway/gateway.go$|\ - ^gateway/routing/file.go$|\ - ^gateway/xnet/xnet.go$|\ - ^pkg/experimental/colibri/reservation/types.go$|\ - ^pkg/experimental/epic/epic_test.go$|\ - ^pkg/experimental/hiddenpath/beaconwriter_test.go$|\ - ^pkg/experimental/hiddenpath/grpc/registerer_test.go$|\ - ^pkg/experimental/hiddenpath/store_test.go$|\ - ^pkg/grpc/dialer_test.go$|\ - ^pkg/log/log.go$|\ - ^pkg/log/testlog/log.go$|\ - ^pkg/private/xtest/graph/graph.go$|\ - ^pkg/private/xtest/grpc.go$|\ - ^pkg/segment/seg.go$|\ - ^pkg/segment/segs_test.go$|\ - ^pkg/slayers/extn_test.go$|\ - ^pkg/slayers/scion_test.go$|\ - ^pkg/snet/packet_test.go$|\ - ^pkg/snet/path.go$|\ - ^pkg/snet/squic/net.go$|\ - ^pkg/sock/reliable/reconnect/conn.go$|\ ^pkg/sock/reliable/reconnect/conn_io_test.go$|\ ^pkg/sock/reliable/reconnect/network_test.go$|\ - ^pkg/sock/reliable/reconnect/reconnecter_test.go$|\ - ^pkg/sock/reliable/reliable.go$|\ - ^private/app/appnet/infraenv.go$|\ - ^private/app/launcher/launcher.go$|\ - ^private/app/path/pathprobe/paths.go$|\ - ^private/config/sample.go$|\ - ^private/mgmtapi/cppki/api/api.go$|\ - ^private/mgmtapi/segments/api/api.go$|\ - ^private/path/combinator/combinator.go$|\ - ^private/revcache/revcachetest/revcachetest.go$|\ - ^private/service/statuspages.go$|\ - ^private/storage/trust/fspersister/db_test.go$|\ - ^private/svc/internal/ctxconn/ctxconn.go$|\ - ^private/trust/db_inspector.go$|\ - ^private/trust/verifier.go$|\ - ^private/trust/verifier_bench_test.go$|\ - ^private/worker/worker_test.go$|\ - ^router/dataplane_test.go$|\ - ^router/export_test.go$|\ - ^router/mgmtapi/api.go$|\ - ^scion-pki/trcs/combine_test.go$|\ - ^tools/end2end/main.go$|\ - ^tools/end2end_integration/main.go$|\ - ^tools/integration/binary.go$|\ - ^tools/integration/done.go$|\ - ^tools/integration/integration.go$|\ - ^tools/integration/progress/progress.go$" - linters: [errcheck] + ^pkg/sock/reliable/reconnect/reconnecter_test.go$" diff --git a/control/beacon/policy.go b/control/beacon/policy.go index 8a99e1a69..9630520e2 100644 --- a/control/beacon/policy.go +++ b/control/beacon/policy.go @@ -204,14 +204,11 @@ func (p *Policy) InitDefaults() { p.Filter.InitDefaults() } -func (p *Policy) initDefaults(t PolicyType) error { +func (p *Policy) initDefaults(t PolicyType) { p.InitDefaults() - if p.Type != "" && p.Type != t { - return serrors.New("Specified policy type does not match", - "expected", t, "actual", p.Type) + if p.Type == "" { + p.Type = t } - p.Type = t - return nil } // ParsePolicyYaml parses the policy in yaml format and initializes the default values. @@ -220,9 +217,11 @@ func ParsePolicyYaml(b []byte, t PolicyType) (*Policy, error) { if err := yaml.UnmarshalStrict(b, p); err != nil { return nil, serrors.WrapStr("Unable to parse policy", err) } - if err := p.initDefaults(t); err != nil { - return nil, err + if p.Type != "" && p.Type != t { + return nil, serrors.New("specified policy type does not match", + "expected", t, "actual", p.Type) } + p.initDefaults(t) return p, nil } diff --git a/control/beacon/policy_test.go b/control/beacon/policy_test.go index 26297f043..c2c3a62de 100644 --- a/control/beacon/policy_test.go +++ b/control/beacon/policy_test.go @@ -55,7 +55,7 @@ func TestLoadPolicyFromYaml(t *testing.T) { ErrAssertion: assert.Error, }, "policy without type": { - File: "testdata/typedPolicy.yml", + File: "testdata/policy.yml", Type: beacon.PropPolicy, ErrAssertion: assert.NoError, }, diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index 4dd447cb5..2f53c2ca9 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -510,9 +510,13 @@ func realMain(ctx context.Context) error { periodic.Func{ TaskName: "signer generator", Task: func(ctx context.Context) { - signer.Sign(ctx, []byte{}) + if _, err := signer.Sign(ctx, []byte{}); err != nil { + log.Info("Failed signer health check", "err", err) + } if chainBuilder.PolicyGen != nil { - chainBuilder.PolicyGen.Generate(ctx) + if _, err := chainBuilder.PolicyGen.Generate(ctx); err != nil { + log.Info("Failed renewal signer health check", "err", err) + } } }, }, diff --git a/control/colibri/reservation/conf/capacities_test.go b/control/colibri/reservation/conf/capacities_test.go index e037ba51e..481861976 100644 --- a/control/colibri/reservation/conf/capacities_test.go +++ b/control/colibri/reservation/conf/capacities_test.go @@ -59,7 +59,7 @@ func TestJson(t *testing.T) { name, tc := name, tc t.Run(name, func(t *testing.T) { t.Parallel() - tc.cap.init() + require.NoError(t, tc.cap.init()) buf, err := json.MarshalIndent(tc.cap, "", " ") buf = append(buf, '\n') require.NoError(t, err) diff --git a/control/colibri/reservation/segment/path.go b/control/colibri/reservation/segment/path.go index 6e20beac5..a2eb8afec 100644 --- a/control/colibri/reservation/segment/path.go +++ b/control/colibri/reservation/segment/path.go @@ -126,7 +126,7 @@ func (p ReservationTransparentPath) ToRaw() []byte { return nil } buff := make([]byte, p.Len()) - p.Read(buff) + _, _ = p.Read(buff) return buff } diff --git a/control/mgmtapi/api.go b/control/mgmtapi/api.go index fd07d3c89..8bc9526e3 100644 --- a/control/mgmtapi/api.go +++ b/control/mgmtapi/api.go @@ -21,7 +21,6 @@ import ( "encoding/json" "encoding/pem" "fmt" - "io" "net/http" "sort" "time" @@ -455,7 +454,7 @@ func (s *Server) GetBeaconBlob(w http.ResponseWriter, r *http.Request, segmentId }) return } - io.Copy(w, &buf) + _, _ = w.Write(buf.Bytes()) } // GetSegments gets the stored in the PathDB. @@ -672,7 +671,7 @@ func (s *Server) GetSignerChain(w http.ResponseWriter, r *http.Request) { return } } - io.Copy(w, &buf) + _, _ = w.Write(buf.Bytes()) } // GetTopology is an indirection to the http handler. @@ -799,5 +798,5 @@ func Error(w http.ResponseWriter, p Problem) { enc := json.NewEncoder(w) enc.SetIndent("", " ") // no point in catching error here, there is nothing we can do about it anymore. - enc.Encode(p) + _ = enc.Encode(p) } diff --git a/dispatcher/cmd/dispatcher/main.go b/dispatcher/cmd/dispatcher/main.go index d078b19c9..ab26beac3 100644 --- a/dispatcher/cmd/dispatcher/main.go +++ b/dispatcher/cmd/dispatcher/main.go @@ -116,7 +116,11 @@ func realMain(ctx context.Context) error { return globalCfg.Metrics.ServePrometheus(errCtx) }) - defer deleteSocket(globalCfg.Dispatcher.ApplicationSocket) + defer func() { + if err := deleteSocket(globalCfg.Dispatcher.ApplicationSocket); err != nil { + log.Error("deleting socket", "err", err) + } + }() g.Go(func() error { defer log.HandlePanic() diff --git a/dispatcher/cmd/dispatcher/main_test.go b/dispatcher/cmd/dispatcher/main_test.go index 3d6fbe682..d3c4023d6 100644 --- a/dispatcher/cmd/dispatcher/main_test.go +++ b/dispatcher/cmd/dispatcher/main_test.go @@ -485,8 +485,3 @@ func MustPack(pkt snet.Packet) []byte { } return pkt.Bytes } - -func TestMain(m *testing.M) { - // log.Setup(log.Config{Console: log.ConsoleConfig{Level: "debug"}}) - os.Exit(m.Run()) -} diff --git a/dispatcher/dispatcher.go b/dispatcher/dispatcher.go index ae7daf4dc..f38bf52d8 100644 --- a/dispatcher/dispatcher.go +++ b/dispatcher/dispatcher.go @@ -141,7 +141,7 @@ func (ac *Conn) Write(pkt *respool.Packet) (int, error) { // with the dispatcher. Likelihood that they overlap is very small. // If this becomes ever a problem, we can namespace the ID per registered // application. - registerIfSCMPInfo(ac.regReference, pkt) + _ = registerIfSCMPInfo(ac.regReference, pkt) return pkt.SendOnConn(ac.conn, pkt.UnderlayRemote) } diff --git a/dispatcher/internal/registration/bench_test.go b/dispatcher/internal/registration/bench_test.go index 0c7bbe5b5..84d5e3190 100644 --- a/dispatcher/internal/registration/bench_test.go +++ b/dispatcher/internal/registration/bench_test.go @@ -57,7 +57,8 @@ func BenchmarkRegister(b *testing.B) { regData := generateRegisterArgs(b.N) b.ResetTimer() for n := 0; n < b.N; n++ { - table.Register(regData[n].ia, regData[n].public, nil, addr.SvcNone, regData[n].value) + _, _ = table.Register(regData[n].ia, regData[n].public, nil, + addr.SvcNone, regData[n].value) } } @@ -66,7 +67,8 @@ func BenchmarkLookupPublicIPv4(b *testing.B) { table := NewIATable(minPort, maxPort) regData := generateRegisterArgs(numEntries) for i := 0; i < numEntries; i++ { - table.Register(regData[i].ia, regData[i].public, nil, addr.SvcNone, regData[i].value) + _, _ = table.Register(regData[i].ia, regData[i].public, nil, + addr.SvcNone, regData[i].value) } lookupData := generateLookupPublicArgs(b.N) b.ResetTimer() @@ -96,7 +98,7 @@ func BenchmarkLookupServiceIPv4(b *testing.B) { table := NewIATable(minPort, maxPort) regData := generateRegisterArgs(numEntries) for i := 0; i < numEntries; i++ { - table.Register(regData[i].ia, regData[i].public, regData[i].bind, + _, _ = table.Register(regData[i].ia, regData[i].public, regData[i].bind, regData[i].svc, regData[i].value) } lookupData := generateLookupServiceArgs(b.N) diff --git a/gateway/control/BUILD.bazel b/gateway/control/BUILD.bazel index 1c77f7052..f00b574b0 100644 --- a/gateway/control/BUILD.bazel +++ b/gateway/control/BUILD.bazel @@ -87,5 +87,6 @@ go_test( "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", + "@org_golang_x_sync//errgroup:go_default_library", ], ) diff --git a/gateway/control/aggregator.go b/gateway/control/aggregator.go index 1c6944d82..c50ebaa04 100644 --- a/gateway/control/aggregator.go +++ b/gateway/control/aggregator.go @@ -111,7 +111,7 @@ func (a *Aggregator) run(ctx context.Context) error { // Close stops the internal goroutines. func (a *Aggregator) Close(ctx context.Context) { - a.workerBase.CloseWrapper(ctx, nil) + _ = a.workerBase.CloseWrapper(ctx, nil) } // Prefixes pushes new set of prefixes for a specific gateway. diff --git a/gateway/control/engine.go b/gateway/control/engine.go index 1cf229832..0c69af880 100644 --- a/gateway/control/engine.go +++ b/gateway/control/engine.go @@ -128,29 +128,29 @@ func (e *Engine) DiagnosticsWrite(w io.Writer) { } raw, err := json.MarshalIndent(d, "", " ") if err != nil { - w.Write([]byte(fmt.Sprintf("Error collecting Engine diagnostics %v", err))) + fmt.Fprintf(w, "Error collecting Engine diagnostics %v", err) return } - w.Write(raw) - w.Write([]byte("\n")) + _, _ = w.Write(raw) + fmt.Fprint(w, "\n") - w.Write([]byte("Last seen session configs:\n")) + fmt.Fprint(w, "Last seen session configs:\n") raw, err = json.MarshalIndent(e.SessionConfigs, "", " ") if err != nil { - w.Write([]byte(fmt.Sprintf("Error collecting Engine SessionConfigs diagnostics %v", err))) + fmt.Fprintf(w, "Error collecting Engine SessionConfigs diagnostics %v", err) return } - w.Write(raw) - w.Write([]byte("\n")) + _, _ = w.Write(raw) + fmt.Fprint(w, "\n") - w.Write([]byte("Control-plane routing table:\n")) + fmt.Fprint(w, "Control-plane routing table:\n") e.router.DiagnosticsWrite(w) - w.Write([]byte("\n")) + fmt.Fprint(w, "\n") if dw, ok := e.RoutingTable.(DiagnosticsWriter); ok { - w.Write([]byte("Data-plane routing table:\n")) + fmt.Fprint(w, "Data-plane routing table:\n") dw.DiagnosticsWrite(w) - w.Write([]byte("\n")) + fmt.Fprint(w, "\n") } } @@ -226,19 +226,19 @@ func (e *Engine) Status(w io.Writer) { for _, s := range iaSessions { fmt.Fprintf(w, " SESSION %d, POLICY_ID %d, REMOTE: %s, HEALTHY %t\n", s.ID, s.PolicyID, s.ProbeAddr, s.Healthy) - fmt.Fprintf(w, " PATHS:\n") + fmt.Fprint(w, " PATHS:\n") renderPathInfo(s.PathInfo, w, 2) - fmt.Fprintf(w, "\n") + fmt.Fprint(w, "\n") } } for _, ia := range sortedIAs { - w.Write([]byte(fmt.Sprintf("ISD-AS %s\n", ia))) + fmt.Fprintf(w, "ISD-AS %s\n", ia) printSessions(sessions[ia]) - w.Write([]byte("\n")) + fmt.Fprint(w, "\n") } if dw, ok := e.RoutingTable.(DiagnosticsWriter); ok { - w.Write([]byte("\nROUTING TABLE:\n")) + fmt.Fprint(w, "\nROUTING TABLE:\n") dw.DiagnosticsWrite(w) } } diff --git a/gateway/control/engine_test.go b/gateway/control/engine_test.go index 2d88afcfa..fc1682fef 100644 --- a/gateway/control/engine_test.go +++ b/gateway/control/engine_test.go @@ -22,6 +22,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" "github.com/scionproto/scion/gateway/control" "github.com/scionproto/scion/gateway/control/mock_control" @@ -41,12 +42,14 @@ func TestEngineRun(t *testing.T) { DataplaneSessionFactory: mock_control.NewMockDataplaneSessionFactory(ctrl), } - go func() { - engine.Run(context.Background()) - }() + var bg errgroup.Group + bg.Go(func() error { + return engine.Run(context.Background()) + }) time.Sleep(50 * time.Millisecond) err := engine.Run(context.Background()) assert.Error(t, err) + assert.NoError(t, bg.Wait()) }) t.Run("nil routing table", func(t *testing.T) { diff --git a/gateway/control/enginecontroller_test.go b/gateway/control/enginecontroller_test.go index e0081c849..c981be84c 100644 --- a/gateway/control/enginecontroller_test.go +++ b/gateway/control/enginecontroller_test.go @@ -22,6 +22,7 @@ import ( "github.com/golang/mock/gomock" "github.com/google/gopacket" "github.com/stretchr/testify/assert" + "golang.org/x/sync/errgroup" "github.com/scionproto/scion/gateway/control" "github.com/scionproto/scion/gateway/control/mock_control" @@ -47,12 +48,15 @@ func TestEngineControllerRun(t *testing.T) { EngineFactory: engineFactory, } - go func() { - engineController.Run(context.Background()) - }() + var bg errgroup.Group + bg.Go(func() error { + return engineController.Run(context.Background()) + }) time.Sleep(50 * time.Millisecond) err := engineController.Run(context.Background()) assert.Error(t, err) + close(configurationUpdates) + assert.NoError(t, bg.Wait()) }) t.Run("nil configuration updates", func(t *testing.T) { diff --git a/gateway/control/export_test.go b/gateway/control/export_test.go index 8093e1c73..8597e7533 100644 --- a/gateway/control/export_test.go +++ b/gateway/control/export_test.go @@ -16,7 +16,8 @@ package control import ( "context" - "sync" + + "golang.org/x/sync/errgroup" ) var ( @@ -36,18 +37,16 @@ func (w *GatewayWatcher) RunOnce(ctx context.Context) { w.run(ctx) } -func (w *GatewayWatcher) RunAllPrefixWatchersOnceForTest(ctx context.Context) { - var wg sync.WaitGroup +func (w *GatewayWatcher) RunAllPrefixWatchersOnceForTest(ctx context.Context) error { + var eg errgroup.Group for _, wi := range w.currentWatchers { wi := wi wi.prefixWatcher.resetRunMarker() - wg.Add(1) - go func() { - defer wg.Done() - wi.prefixWatcher.Run(ctx) - }() + eg.Go(func() error { + return wi.prefixWatcher.Run(ctx) + }) } - wg.Wait() + return eg.Wait() } func (w *prefixWatcher) resetRunMarker() { diff --git a/gateway/control/remotemonitor.go b/gateway/control/remotemonitor.go index 4b014b1f8..fa3ddf158 100644 --- a/gateway/control/remotemonitor.go +++ b/gateway/control/remotemonitor.go @@ -194,7 +194,7 @@ func (rm *RemoteMonitor) DiagnosticsWrite(w io.Writer) { var err error diagnostics.Remotes[ia], err = gatewaywatcher.diagnostics() if err != nil { - w.Write([]byte(fmt.Sprintf("Error collecting diagnostics from gateways %v", err))) + fmt.Fprintf(w, "Error collecting diagnostics from gateways %v", err) return } } @@ -202,7 +202,7 @@ func (rm *RemoteMonitor) DiagnosticsWrite(w io.Writer) { enc := json.NewEncoder(w) enc.SetIndent("", " ") if err := enc.Encode(diagnostics); err != nil { - w.Write([]byte(fmt.Sprintf("Error collecting Remotes diagnostics %v", err))) + fmt.Fprintf(w, "Error collecting Remotes diagnostics %v", err) return } } diff --git a/gateway/control/router.go b/gateway/control/router.go index d78f55adf..fb3fe8490 100644 --- a/gateway/control/router.go +++ b/gateway/control/router.go @@ -276,9 +276,9 @@ func (r *Router) DiagnosticsWrite(w io.Writer) { } raw, err := json.MarshalIndent(d, "", " ") if err != nil { - w.Write([]byte(fmt.Sprintf("Error collecting Router diagnostics %v", err))) + fmt.Fprintf(w, "Error collecting Router diagnostics %v", err) return } - w.Write(raw) - w.Write([]byte("\n")) + _, _ = w.Write(raw) + fmt.Fprint(w, "\n") } diff --git a/gateway/control/session.go b/gateway/control/session.go index d020340b0..61fbe8f1c 100644 --- a/gateway/control/session.go +++ b/gateway/control/session.go @@ -134,7 +134,9 @@ func (s *Session) Run(ctx context.Context) error { diff.log(logger) } s.pathResult = newPathResult - s.DataplaneSession.SetPaths(s.pathResult.Paths) + if err := s.DataplaneSession.SetPaths(s.pathResult.Paths); err != nil { + logger.Error("setting paths", "err", err) + } s.pathResultMtx.Unlock() } } diff --git a/gateway/control/sessionconfigurator.go b/gateway/control/sessionconfigurator.go index fd2dc1b6a..98791d097 100644 --- a/gateway/control/sessionconfigurator.go +++ b/gateway/control/sessionconfigurator.go @@ -111,11 +111,11 @@ func (sc *SessionConfigurator) DiagnosticsWrite(w io.Writer) { } raw, err := json.MarshalIndent(d, "", " ") if err != nil { - w.Write([]byte(fmt.Sprintf("Error writing SessionConfigurator diagnostics: %v", err))) + fmt.Fprintf(w, "Error writing SessionConfigurator diagnostics: %v", err) return } - w.Write(raw) - w.Write([]byte("\n")) + _, _ = w.Write(raw) + fmt.Fprint(w, "\n") } func (sc *SessionConfigurator) run(ctx context.Context) error { diff --git a/gateway/control/watcher_test.go b/gateway/control/watcher_test.go index 9df81cc27..e520cacc1 100644 --- a/gateway/control/watcher_test.go +++ b/gateway/control/watcher_test.go @@ -23,6 +23,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" "github.com/scionproto/scion/gateway/control" "github.com/scionproto/scion/gateway/control/mock_control" @@ -79,7 +80,14 @@ func TestGatewayWatcherRun(t *testing.T) { // run initially remotes.Set(0) ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) - go w.Run(ctx) + var bg errgroup.Group + bg.Go(func() error { + return w.Run(ctx) + }) + t.Cleanup(func() { + assert.NoError(t, bg.Wait()) + }) + for { if metrics.GaugeValue(remotes) > 0 { break @@ -107,7 +115,7 @@ func TestGatewayWatcherRun(t *testing.T) { // nothing really checks the context except the run loop, so we can // immediately cancel and then it will run only once. cancel() - w.RunAllPrefixWatchersOnceForTest(ctx) + assert.NoError(t, w.RunAllPrefixWatchersOnceForTest(ctx)) assert.Equal(t, 2, int(metrics.CounterValue(g1))) assert.Equal(t, 1, int(metrics.CounterValue(g2))) @@ -170,7 +178,13 @@ func TestPrefixWatcherRun(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) defer cancel() - go w.Run(ctx) + var bg errgroup.Group + bg.Go(func() error { + return w.Run(ctx) + }) + t.Cleanup(func() { + assert.NoError(t, bg.Wait()) + }) <-ctx.Done() time.Sleep(10 * time.Millisecond) diff --git a/gateway/dataplane/diagnostics_test.go b/gateway/dataplane/diagnostics_test.go index 0c61940ad..51dde60dd 100644 --- a/gateway/dataplane/diagnostics_test.go +++ b/gateway/dataplane/diagnostics_test.go @@ -55,8 +55,8 @@ func TestDiagnosticWriter(t *testing.T) { }, }, }) - dp.SetSession(1, testPktWriter{ID: 1}) - dp.SetSession(2, testPktWriter{ID: 2}) + require.NoError(t, dp.SetSession(1, testPktWriter{ID: 1})) + require.NoError(t, dp.SetSession(2, testPktWriter{ID: 2})) return dp }, wantFile: "./testdata/routingtable1.txt", diff --git a/gateway/dataplane/ipforwarder_test.go b/gateway/dataplane/ipforwarder_test.go index d21f21464..d673f582f 100644 --- a/gateway/dataplane/ipforwarder_test.go +++ b/gateway/dataplane/ipforwarder_test.go @@ -163,16 +163,10 @@ func TestIPForwarderRun(t *testing.T) { art.SetRoutingTable(rt) sessionOne := mock_control.NewMockPktWriter(ctrl) - rt.SetSession( - 1, - sessionOne, - ) + require.NoError(t, rt.SetSession(1, sessionOne)) sessionTwo := mock_control.NewMockPktWriter(ctrl) - rt.SetSession( - 2, - sessionTwo, - ) + require.NoError(t, rt.SetSession(2, sessionTwo)) ipv4Packet := newIPv4Packet(t, net.IP{10, 0, 0, 1}) reader.EXPECT().Read(gomock.Any()).DoAndReturn( diff --git a/gateway/dataplane/routingtable.go b/gateway/dataplane/routingtable.go index bb2d4e8a3..769701972 100644 --- a/gateway/dataplane/routingtable.go +++ b/gateway/dataplane/routingtable.go @@ -107,7 +107,7 @@ func (rt *RoutingTable) DiagnosticsWrite(w io.Writer) { raw += e.String() } - w.Write([]byte(raw)) + _, _ = w.Write([]byte(raw)) } // RouteIPv4 returns the session the IPv4 packet should be routed on. It returns after doing a diff --git a/gateway/dataplane/session_test.go b/gateway/dataplane/session_test.go index ab55c656c..042ae7e23 100644 --- a/gateway/dataplane/session_test.go +++ b/gateway/dataplane/session_test.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.uber.org/goleak" "github.com/scionproto/scion/pkg/private/mocks/net/mock_net" @@ -50,7 +51,7 @@ func TestSinglePath(t *testing.T) { frameChan := make(chan ([]byte)) sess := createSession(t, ctrl, frameChan) - sess.SetPaths([]snet.Path{createMockPath(ctrl, 200)}) + require.NoError(t, sess.SetPaths([]snet.Path{createMockPath(ctrl, 200)})) sendPackets(t, sess, 22, 10) waitFrames(t, frameChan, 22, 10) sess.Close() @@ -66,17 +67,17 @@ func TestTwoPaths(t *testing.T) { sess := createSession(t, ctrl, frameChan) - sess.SetPaths([]snet.Path{createMockPath(ctrl, 200)}) + require.NoError(t, sess.SetPaths([]snet.Path{createMockPath(ctrl, 200)})) sendPackets(t, sess, 22, 10) // Reuse the same path, thus reusing the sender. - sess.SetPaths([]snet.Path{createMockPath(ctrl, 200)}) + require.NoError(t, sess.SetPaths([]snet.Path{createMockPath(ctrl, 200)})) sendPackets(t, sess, 22, 10) // The previous packets are not yet sent, yet we set a new path thus creating a new // sender. The goal is to test that the old packets will still be sent out. // The MTU is used to differentiate the paths - sess.SetPaths([]snet.Path{createMockPath(ctrl, 202)}) + require.NoError(t, sess.SetPaths([]snet.Path{createMockPath(ctrl, 202)})) sendPackets(t, sess, 22, 10) waitFrames(t, frameChan, 22, 30) @@ -100,15 +101,15 @@ func TestNoLeak(t *testing.T) { batchSize := 10 for i := 0; i < iterations; i++ { - sess.SetPaths([]snet.Path{createMockPath(ctrl, 200)}) + require.NoError(t, sess.SetPaths([]snet.Path{createMockPath(ctrl, 200)})) sendPackets(t, sess, payloadLen, batchSize) - sess.SetPaths([]snet.Path{ + require.NoError(t, sess.SetPaths([]snet.Path{ createMockPath(ctrl, 200), createMockPath(ctrl, 201), createMockPath(ctrl, 202), createMockPath(ctrl, 203), - }) + })) sendPackets(t, sess, payloadLen, batchSize) // Cause error diff --git a/gateway/gateway.go b/gateway/gateway.go index d437c1bdf..bdd994d5d 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -757,9 +757,13 @@ func (g *Gateway) diagnosticsSGRP( d.Learned.Dynamic = append(d.Learned.Dynamic, r.Prefix.String()) } } - enc := json.NewEncoder(w) - enc.SetIndent("", " ") - enc.Encode(d) + jsonData, err := json.MarshalIndent(d, "", " ") + if err != nil { + log.Error("json marshalling", "err", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + _, _ = w.Write(jsonData) } } diff --git a/gateway/routing/file.go b/gateway/routing/file.go index 8a1f0eea1..80a2b74e5 100644 --- a/gateway/routing/file.go +++ b/gateway/routing/file.go @@ -17,7 +17,6 @@ package routing import ( - "bytes" "fmt" "io" "net/http" @@ -65,7 +64,7 @@ func NewPolicyHandler(policyPublisher PolicyPublisher, http.StatusInternalServerError) return } - io.Copy(w, bytes.NewReader(raw)) + _, _ = w.Write(raw) case http.MethodPut: rawPolicy, err := io.ReadAll(r.Body) if err != nil { diff --git a/gateway/xnet/xnet.go b/gateway/xnet/xnet.go index 8496cf0f6..7c9f64639 100644 --- a/gateway/xnet/xnet.go +++ b/gateway/xnet/xnet.go @@ -68,8 +68,8 @@ func connectTun(name string) (netlink.Link, io.ReadWriteCloser, error) { return link, tun, nil Cleanup: // Don't check for errors, as we're already handling one. - tun.Close() - netlink.LinkDel(link) + _ = tun.Close() + _ = netlink.LinkDel(link) return nil, nil, err } diff --git a/pkg/experimental/colibri/reservation/types.go b/pkg/experimental/colibri/reservation/types.go index 96ced0fc4..5166dfc13 100644 --- a/pkg/experimental/colibri/reservation/types.go +++ b/pkg/experimental/colibri/reservation/types.go @@ -84,7 +84,7 @@ func (id *SegmentID) Read(raw []byte) (int, error) { // ToRaw calls Read and returns a new allocated buffer with the ID serialized. func (id *SegmentID) ToRaw() []byte { buf := make([]byte, SegmentIDLen) - id.Read(buf) // safely ignore errors as they can only come from buffer size + _, _ = id.Read(buf) // safely ignore errors as they can only come from buffer size return buf } @@ -146,7 +146,7 @@ func (id *E2EID) Read(raw []byte) (int, error) { // ToRaw calls Read and returns a new allocated buffer with the ID serialized. func (id *E2EID) ToRaw() []byte { buf := make([]byte, E2EIDLen) - id.Read(buf) // safely ignore errors as they can only come from buffer size + _, _ = id.Read(buf) // safely ignore errors as they can only come from buffer size return buf } @@ -349,7 +349,7 @@ func (f *InfoField) ToRaw() []byte { var buff []byte = nil if f != nil { buff = make([]byte, InfoFieldLen) - f.Read(buff) // safely ignore errors as they can only come from buffer size + _, _ = f.Read(buff) // safely ignore errors as they can only come from buffer size } return buff } @@ -496,7 +496,7 @@ func (hf *HopField) Read(b []byte) (int, error) { // ToRaw returns the serial representation of the HopField. func (hf *HopField) ToRaw() []byte { buff := make([]byte, HopFieldLen) - hf.Read(buff) // discard returned values + _, _ = hf.Read(buff) // discard returned values return buff } @@ -567,7 +567,7 @@ func (t *Token) Read(b []byte) (int, error) { return 0, err } for i := 0; i < len(t.HopFields); i++ { - t.HopFields[i].Read(b[offset : offset+HopFieldLen]) + _, _ = t.HopFields[i].Read(b[offset : offset+HopFieldLen]) offset += HopFieldLen } return offset, nil @@ -578,7 +578,7 @@ func (t *Token) ToRaw() []byte { var buff []byte = nil if t != nil { buff = make([]byte, t.Len()) - t.Read(buff) // safely ignore errors as they can only come from buffer size + _, _ = t.Read(buff) // safely ignore errors as they can only come from buffer size } return buff } diff --git a/pkg/experimental/epic/epic_test.go b/pkg/experimental/epic/epic_test.go index 9c08f2ffc..6de95ac23 100644 --- a/pkg/experimental/epic/epic_test.go +++ b/pkg/experimental/epic/epic_test.go @@ -38,7 +38,7 @@ func TestPrepareMacInput(t *testing.T) { Want []byte }{ "Correct input": { - ScionHeader: createScionCmnAddrHdr(), + ScionHeader: createScionCmnAddrHdr(t), errorFunc: assert.NoError, Want: []byte( "\x00\x4a\xf9\xf0\x70\x00\x00\x00\x01\x02\x00\x00\x03" + @@ -192,7 +192,7 @@ func TestVerifyTimestamp(t *testing.T) { func TestVerifyHVF(t *testing.T) { // Create packet - s := createScionCmnAddrHdr() + s := createScionCmnAddrHdr(t) now := time.Now().Truncate(time.Second) timestamp := uint32(now.Add(-time.Minute).Unix()) epicTS, _ := libepic.CreateTimestamp(now.Add(-time.Minute), time.Now()) @@ -378,13 +378,14 @@ func TestCoreFromPktCounter(t *testing.T) { } } -func createScionCmnAddrHdr() *slayers.SCION { +func createScionCmnAddrHdr(t *testing.T) *slayers.SCION { + t.Helper() spkt := &slayers.SCION{ SrcIA: xtest.MustParseIA("2-ff00:0:222"), PayloadLen: 120, } ip4Addr := &net.IPAddr{IP: net.ParseIP("10.0.0.100")} - spkt.SetSrcAddr(ip4Addr) + require.NoError(t, spkt.SetSrcAddr(ip4Addr)) return spkt } diff --git a/pkg/experimental/hiddenpath/beaconwriter_test.go b/pkg/experimental/hiddenpath/beaconwriter_test.go index 7c7bb6ac5..89a6188cf 100644 --- a/pkg/experimental/hiddenpath/beaconwriter_test.go +++ b/pkg/experimental/hiddenpath/beaconwriter_test.go @@ -218,7 +218,9 @@ func TestRemoteBeaconWriterWrite(t *testing.T) { ctx, cancelF := context.WithTimeout(context.Background(), time.Second) defer cancelF() - w.Write(ctx, beacons, sortedIntfs(intfs, topology.Peer)) + stats, err := w.Write(ctx, beacons, sortedIntfs(intfs, topology.Peer)) + assert.NoError(t, err) + assert.Equal(t, len(beacons), stats.Count) }) } } diff --git a/pkg/experimental/hiddenpath/grpc/lookup_test.go b/pkg/experimental/hiddenpath/grpc/lookup_test.go index 96d9e8a1a..6b7becdc8 100644 --- a/pkg/experimental/hiddenpath/grpc/lookup_test.go +++ b/pkg/experimental/hiddenpath/grpc/lookup_test.go @@ -39,7 +39,7 @@ import ( ) func TestSegmentServerHiddenSegments(t *testing.T) { - segsMeta, wantPB := createSegs() + segsMeta, wantPB := createSegs(t) testCases := map[string]struct { createCtx func(t *testing.T) context.Context @@ -103,7 +103,7 @@ func TestSegmentServerHiddenSegments(t *testing.T) { } func TestAuthoritativeSegmentServerAuthoritativeHiddenSegments(t *testing.T) { - segsMeta, _ := createSegs() + segsMeta, _ := createSegs(t) marshalBody := func(t *testing.T, body *hspb.HiddenSegmentsRequest) []byte { r, err := proto.Marshal(body) @@ -285,8 +285,10 @@ func groupIDsToInts(ids []hiddenpath.GroupID) []uint64 { return result } -func createSegs() ([]*seg.Meta, *hspb.HiddenSegmentsResponse) { - s := createSeg() +func createSegs(t *testing.T) ([]*seg.Meta, *hspb.HiddenSegmentsResponse) { + t.Helper() + + s := createSeg(t) ret1 := []*seg.Meta{&s} ret2 := &hspb.HiddenSegmentsResponse{ Segments: grpc.ToHSPB(ret1), diff --git a/pkg/experimental/hiddenpath/grpc/registerer_test.go b/pkg/experimental/hiddenpath/grpc/registerer_test.go index 88868c52e..cfff599c5 100644 --- a/pkg/experimental/hiddenpath/grpc/registerer_test.go +++ b/pkg/experimental/hiddenpath/grpc/registerer_test.go @@ -22,6 +22,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/scionproto/scion/control/beaconing" "github.com/scionproto/scion/control/beaconing/mock_beaconing" @@ -66,7 +67,7 @@ func TestRegistererRegisterSegment(t *testing.T) { }, input: hiddenpath.SegmentRegistration{ GroupID: hiddenpath.GroupID{Suffix: 42}, - Seg: createSeg(), + Seg: createSeg(t), }, assertErr: assert.NoError, }, @@ -86,7 +87,7 @@ func TestRegistererRegisterSegment(t *testing.T) { return r }, input: hiddenpath.SegmentRegistration{ - Seg: createSeg(), + Seg: createSeg(t), }, assertErr: assert.NoError, }, @@ -118,7 +119,8 @@ func TestRegistererRegisterSegment(t *testing.T) { } -func createSeg() seg.Meta { +func createSeg(t *testing.T) seg.Meta { + t.Helper() asEntry := seg.ASEntry{ Local: xtest.MustParseIA("1-ff00:0:110"), HopEntry: seg.HopEntry{ @@ -126,7 +128,7 @@ func createSeg() seg.Meta { }, } ps, _ := seg.CreateSegment(time.Now(), 1337) - ps.AddASEntry(context.Background(), asEntry, graph.NewSigner()) + require.NoError(t, ps.AddASEntry(context.Background(), asEntry, graph.NewSigner())) return seg.Meta{Type: seg.TypeDown, Segment: ps} } diff --git a/pkg/experimental/hiddenpath/grpc/requester_test.go b/pkg/experimental/hiddenpath/grpc/requester_test.go index c0940d566..81bc77ffd 100644 --- a/pkg/experimental/hiddenpath/grpc/requester_test.go +++ b/pkg/experimental/hiddenpath/grpc/requester_test.go @@ -38,7 +38,7 @@ import ( ) func TestRequesterSegments(t *testing.T) { - testSeg := createSeg() + testSeg := createSeg(t) hpID := hiddenpath.GroupID{ OwnerAS: xtest.MustParseAS("ff00:0:2"), Suffix: 15, @@ -138,7 +138,7 @@ func TestRequesterSegments(t *testing.T) { } func TestAuthoritativeRequesterHiddenSegments(t *testing.T) { - testSeg := createSeg() + testSeg := createSeg(t) testCases := map[string]struct { input hiddenpath.SegmentRequest signer func(*gomock.Controller) hpgrpc.Signer diff --git a/pkg/experimental/hiddenpath/store_test.go b/pkg/experimental/hiddenpath/store_test.go index 5372efd9d..a326aba80 100644 --- a/pkg/experimental/hiddenpath/store_test.go +++ b/pkg/experimental/hiddenpath/store_test.go @@ -21,6 +21,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/experimental/hiddenpath" @@ -35,7 +36,7 @@ import ( ) func TestStorerGet(t *testing.T) { - want, dbresult := createSegs() + want, dbresult := createSegs(t) groupID := hiddenpath.GroupID{OwnerAS: xtest.MustParseAS("ff00:0:111"), Suffix: 42} testCases := map[string]struct { inputGroups []hiddenpath.GroupID @@ -101,7 +102,7 @@ func TestStorerGet(t *testing.T) { } func TestStorerPut(t *testing.T) { - want, _ := createSegs() + want, _ := createSegs(t) testCases := map[string]struct { inputGroup hiddenpath.GroupID inputSegs []*seg.Meta @@ -152,7 +153,8 @@ func TestStorerPut(t *testing.T) { } } -func createSegs() ([]*seg.Meta, query.Results) { +func createSegs(t *testing.T) ([]*seg.Meta, query.Results) { + t.Helper() asEntry := seg.ASEntry{ Local: xtest.MustParseIA("1-ff00:0:110"), HopEntry: seg.HopEntry{ @@ -160,7 +162,7 @@ func createSegs() ([]*seg.Meta, query.Results) { }, } ps, _ := seg.CreateSegment(time.Now(), 1337) - ps.AddASEntry(context.Background(), asEntry, graph.NewSigner()) + require.NoError(t, ps.AddASEntry(context.Background(), asEntry, graph.NewSigner())) ret1 := []*seg.Meta{{Type: seg.TypeDown, Segment: ps}} ret2 := query.Results{&query.Result{ diff --git a/pkg/grpc/BUILD.bazel b/pkg/grpc/BUILD.bazel index e93b7512b..fc6a2b1c4 100644 --- a/pkg/grpc/BUILD.bazel +++ b/pkg/grpc/BUILD.bazel @@ -38,5 +38,6 @@ go_test( "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//resolver:go_default_library", "@org_golang_google_grpc_examples//helloworld/helloworld:go_default_library", + "@org_golang_x_sync//errgroup:go_default_library", ], ) diff --git a/pkg/grpc/dialer_test.go b/pkg/grpc/dialer_test.go index 2e8a2b6a5..533f92ebd 100644 --- a/pkg/grpc/dialer_test.go +++ b/pkg/grpc/dialer_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" "google.golang.org/grpc" helloworldpb "google.golang.org/grpc/examples/helloworld/helloworld" "google.golang.org/grpc/resolver" @@ -43,8 +44,14 @@ func TestTCPDial(t *testing.T) { s := grpc.NewServer() helloworldpb.RegisterGreeterServer(s, &server{}) - go func() { s.Serve(lis) }() - defer s.Stop() + var bg errgroup.Group + bg.Go(func() error { + return s.Serve(lis) + }) + defer func() { + s.Stop() + assert.NoError(t, bg.Wait()) + }() getUnusedAddr := func(t *testing.T) string { l, err := net.Listen("tcp4", "127.0.0.1:0") diff --git a/pkg/log/log.go b/pkg/log/log.go index 8528f588e..a0ddbcd7e 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -138,7 +138,8 @@ func HandlePanic() { // Flush writes the logs to the underlying buffer. func Flush() { - zap.L().Sync() + // Deliberately ignore sync error, see https://github.com/uber-go/zap/issues/328 + _ = zap.L().Sync() } // ConsoleLevel allows interacting with the logging level at runtime. @@ -168,7 +169,7 @@ func (l httpLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: lvl := l.a.Level() - enc.Encode(payload{Level: &lvl}) + _ = enc.Encode(payload{Level: &lvl}) case http.MethodPut: lvl, err := func() (*zapcore.Level, error) { switch r.Header.Get("Content-Type") { @@ -203,14 +204,14 @@ func (l httpLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) { }() if err != nil { w.WriteHeader(http.StatusBadRequest) - enc.Encode(errorResponse{Error: err.Error()}) + _ = enc.Encode(errorResponse{Error: err.Error()}) return } l.a.SetLevel(*lvl) - enc.Encode(payload{Level: lvl}) + _ = enc.Encode(payload{Level: lvl}) default: w.WriteHeader(http.StatusMethodNotAllowed) - enc.Encode(errorResponse{ + _ = enc.Encode(errorResponse{ Error: fmt.Sprintf("HTTP method not supported: %v", r.Method), }) } diff --git a/pkg/log/testlog/log.go b/pkg/log/testlog/log.go index 8d0db4a99..ccc5a365a 100644 --- a/pkg/log/testlog/log.go +++ b/pkg/log/testlog/log.go @@ -24,11 +24,6 @@ import ( "github.com/scionproto/scion/pkg/log" ) -// SetupGlobal sets up the global logger that writes to stderr. -func SetupGlobal() { - log.Setup(log.Config{Console: log.ConsoleConfig{Level: "debug"}}) -} - // NewLogger builds a new Logger that logs all messages to the given testing.TB. func NewLogger(t testing.TB, opts ...zaptest.LoggerOption) log.Logger { return &logger{ diff --git a/pkg/private/xtest/BUILD.bazel b/pkg/private/xtest/BUILD.bazel index 02fa51536..aebaf656e 100644 --- a/pkg/private/xtest/BUILD.bazel +++ b/pkg/private/xtest/BUILD.bazel @@ -14,10 +14,12 @@ go_library( "//pkg/addr:go_default_library", "//pkg/scrypto/cppki:go_default_library", "@af_inet_netaddr//:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//credentials:go_default_library", "@org_golang_google_grpc//credentials/insecure:go_default_library", "@org_golang_google_grpc//test/bufconn:go_default_library", + "@org_golang_x_sync//errgroup:go_default_library", ], ) diff --git a/pkg/private/xtest/graph/BUILD.bazel b/pkg/private/xtest/graph/BUILD.bazel index 4c7829628..d5907cf9e 100644 --- a/pkg/private/xtest/graph/BUILD.bazel +++ b/pkg/private/xtest/graph/BUILD.bazel @@ -11,6 +11,7 @@ go_library( deps = [ "//pkg/addr:go_default_library", "//pkg/private/common:go_default_library", + "//pkg/private/serrors:go_default_library", "//pkg/proto/control_plane:go_default_library", "//pkg/proto/crypto:go_default_library", "//pkg/scrypto/cppki:go_default_library", diff --git a/pkg/private/xtest/graph/graph.go b/pkg/private/xtest/graph/graph.go index 4ef23b096..f608624e5 100644 --- a/pkg/private/xtest/graph/graph.go +++ b/pkg/private/xtest/graph/graph.go @@ -38,6 +38,7 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/common" + "github.com/scionproto/scion/pkg/private/serrors" cppb "github.com/scionproto/scion/pkg/proto/control_plane" cryptopb "github.com/scionproto/scion/pkg/proto/crypto" "github.com/scionproto/scion/pkg/scrypto/cppki" @@ -327,7 +328,9 @@ func (g *Graph) beacon(ifids []uint16, addStaticInfo bool) *seg.PathSegment { if addStaticInfo { asEntry.Extensions.StaticInfo = generateStaticInfo(g, currIA, inIF, outIF) } - segment.AddASEntry(context.Background(), asEntry, g.signers[currIA]) + if err := segment.AddASEntry(context.Background(), asEntry, g.signers[currIA]); err != nil { + panic(serrors.WrapStr("adding AS entry", err)) + } inIF = remoteOutIF currIA = g.parents[remoteOutIF] } diff --git a/pkg/private/xtest/grpc.go b/pkg/private/xtest/grpc.go index d0b4112dd..599ffc57f 100644 --- a/pkg/private/xtest/grpc.go +++ b/pkg/private/xtest/grpc.go @@ -16,9 +16,12 @@ package xtest import ( "context" + "errors" "net" "testing" + "github.com/stretchr/testify/assert" + "golang.org/x/sync/errgroup" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" @@ -68,8 +71,21 @@ func (s *GRPCService) Server() *grpc.Server { } func (s *GRPCService) Start(t *testing.T) { - go func() { s.server.Serve(s.listener) }() - t.Cleanup(s.server.Stop) + var bg errgroup.Group + bg.Go(func() error { + return s.server.Serve(s.listener) + }) + t.Cleanup(func() { + s.server.Stop() + err := bg.Wait() + if errors.Is(err, grpc.ErrServerStopped) { + // Can (only) occur if Stop in the test cleanup is called before + // server has started. This can happen if the test does not + // actually use the server. + return + } + assert.NoError(t, err) + }) } func (s *GRPCService) Dial(ctx context.Context, addr net.Addr) (*grpc.ClientConn, error) { diff --git a/pkg/segment/seg.go b/pkg/segment/seg.go index d1f102a8d..a1c7d8ce3 100644 --- a/pkg/segment/seg.go +++ b/pkg/segment/seg.go @@ -137,6 +137,7 @@ func (ps *PathSegment) FullID() []byte { return ps.calculateHash(false) } +//nolint:errcheck // hash.Write never returns an error func (ps *PathSegment) calculateHash(hopOnly bool) []byte { h := sha256.New() for _, ase := range ps.ASEntries { diff --git a/pkg/segment/segs_test.go b/pkg/segment/segs_test.go index 6d99d0a02..0dc31d024 100644 --- a/pkg/segment/segs_test.go +++ b/pkg/segment/segs_test.go @@ -91,7 +91,8 @@ func TestFilterSegments(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { segs := Segments(test.Segs) - segs.FilterSegs(test.KeepF) + _, err := segs.FilterSegs(test.KeepF) + assert.NoError(t, err) assert.Equal(t, Segments(test.Filtered), segs) }) } diff --git a/pkg/slayers/extn_test.go b/pkg/slayers/extn_test.go index c799dc0ba..3a8239cbd 100644 --- a/pkg/slayers/extn_test.go +++ b/pkg/slayers/extn_test.go @@ -561,7 +561,8 @@ func prepRawPacketWithExtn(t *testing.T, extns ...slayers.L4ProtocolType) []byte b[1] = 6 // ExtLen, see rawTLVOptionsXY copy(b[2:], rawTLVOptionsXY) } - buf.AppendBytes(9) // dummy UDP with 1 byte payload + _, err := buf.AppendBytes(9) // dummy UDP with 1 byte payload + require.NoError(t, err) return buf.Bytes() } diff --git a/pkg/slayers/scion_test.go b/pkg/slayers/scion_test.go index c88e1be7d..352398024 100644 --- a/pkg/slayers/scion_test.go +++ b/pkg/slayers/scion_test.go @@ -244,7 +244,7 @@ func TestSCIONSerializeLengthCheck(t *testing.T) { for name, tc := range testCases { t.Run(name, func(t *testing.T) { pkt.Path = path.NewRawPath() - pkt.Path.DecodeFromBytes(make([]byte, tc.pathLen)) + require.NoError(t, pkt.Path.DecodeFromBytes(make([]byte, tc.pathLen))) buffer := gopacket.NewSerializeBuffer() err := pkt.SerializeTo(buffer, gopacket.SerializeOptions{FixLengths: true}) @@ -394,7 +394,8 @@ func BenchmarkDecodePreallocNoParse(b *testing.B) { raw := prepRawPacket(b) s := &slayers.SCION{} for i := 0; i < b.N; i++ { - s.DecodeFromBytes(raw, gopacket.NilDecodeFeedback) + err := s.DecodeFromBytes(raw, gopacket.NilDecodeFeedback) + require.NoError(b, err) } } @@ -402,7 +403,8 @@ func BenchmarkDecodeNoPreallocNoParse(b *testing.B) { raw := prepRawPacket(b) for i := 0; i < b.N; i++ { s := &slayers.SCION{} - s.DecodeFromBytes(raw, gopacket.NilDecodeFeedback) + err := s.DecodeFromBytes(raw, gopacket.NilDecodeFeedback) + require.NoError(b, err) } } @@ -410,9 +412,11 @@ func BenchmarkDecodePreallocFull(b *testing.B) { raw := prepRawPacket(b) s := &slayers.SCION{} for i := 0; i < b.N; i++ { - s.DecodeFromBytes(raw, gopacket.NilDecodeFeedback) + err := s.DecodeFromBytes(raw, gopacket.NilDecodeFeedback) + require.NoError(b, err) p := s.Path.(*scion.Raw) - p.ToDecoded() + _, err = p.ToDecoded() + require.NoError(b, err) } } @@ -421,8 +425,10 @@ func BenchmarkSerializeReuseBuffer(b *testing.B) { buffer := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{FixLengths: true} for i := 0; i < b.N; i++ { - s.SerializeTo(buffer, opts) - buffer.Clear() + err := s.SerializeTo(buffer, opts) + require.NoError(b, err) + err = buffer.Clear() + require.NoError(b, err) } } @@ -431,7 +437,8 @@ func BenchmarkSerializeNoReuseBuffer(b *testing.B) { opts := gopacket.SerializeOptions{FixLengths: true} for i := 0; i < b.N; i++ { buffer := gopacket.NewSerializeBuffer() - s.SerializeTo(buffer, opts) + err := s.SerializeTo(buffer, opts) + require.NoError(b, err) } } @@ -449,9 +456,9 @@ func prepPacket(t testing.TB, c slayers.L4ProtocolType) *slayers.SCION { SrcIA: xtest.MustParseIA("2-ff00:0:222"), Path: &scion.Raw{}, } - spkt.SetDstAddr(ip6Addr) - spkt.SetSrcAddr(ip4Addr) - spkt.Path.DecodeFromBytes(rawPath()) + require.NoError(t, spkt.SetDstAddr(ip6Addr)) + require.NoError(t, spkt.SetSrcAddr(ip4Addr)) + require.NoError(t, spkt.Path.DecodeFromBytes(rawPath())) return spkt } @@ -459,7 +466,7 @@ func prepRawPacket(t testing.TB) []byte { t.Helper() spkt := prepPacket(t, slayers.L4UDP) buffer := gopacket.NewSerializeBuffer() - spkt.SerializeTo(buffer, gopacket.SerializeOptions{FixLengths: true}) + require.NoError(t, spkt.SerializeTo(buffer, gopacket.SerializeOptions{FixLengths: true})) return buffer.Bytes() } diff --git a/pkg/snet/packet_test.go b/pkg/snet/packet_test.go index ac6f62436..f0d32ef55 100644 --- a/pkg/snet/packet_test.go +++ b/pkg/snet/packet_test.go @@ -257,7 +257,7 @@ func convertRawPath(r snet.RawPath) (snet.DataplanePath, error) { func TestPacketSerialize(t *testing.T) { decodedOHP := onehop.Path{} rawOHP := make([]byte, decodedOHP.Len()) - decodedOHP.SerializeTo(rawOHP) + require.NoError(t, decodedOHP.SerializeTo(rawOHP)) testCases := map[string]struct { input snet.Packet diff --git a/pkg/snet/path.go b/pkg/snet/path.go index 9af8a1ef4..8fa12fc03 100644 --- a/pkg/snet/path.go +++ b/pkg/snet/path.go @@ -219,8 +219,14 @@ func Fingerprint(path Path) PathFingerprint { } h := sha256.New() for _, intf := range meta.Interfaces { - binary.Write(h, binary.BigEndian, intf.IA) - binary.Write(h, binary.BigEndian, intf.ID) + if err := binary.Write(h, binary.BigEndian, intf.IA); err != nil { + // hash.Hash.Write may never error. + // The type check in binary.Write should also pass for addr.IA. + panic(err) + } + if err := binary.Write(h, binary.BigEndian, intf.ID); err != nil { + panic(err) + } } return PathFingerprint(h.Sum(nil)) } diff --git a/pkg/snet/squic/net.go b/pkg/snet/squic/net.go index e11ee4ab4..dc0d5f01c 100644 --- a/pkg/snet/squic/net.go +++ b/pkg/snet/squic/net.go @@ -217,8 +217,10 @@ func (c *acceptingConn) acceptStreamOnce() { // Potentially set the deadlines to the values that were set before the // stream was accepted. - c.stream.SetReadDeadline(c.readDeadline) - c.stream.SetWriteDeadline(c.writeDeadline) + c.err = serrors.Join( + c.stream.SetReadDeadline(c.readDeadline), + c.stream.SetWriteDeadline(c.writeDeadline), + ) } func (c *acceptingConn) SetDeadline(t time.Time) error { @@ -398,7 +400,7 @@ func (d ConnDialer) Dial(ctx context.Context, dst net.Addr) (net.Conn, error) { } stream, err := session.OpenStreamSync(ctx) if err != nil { - session.CloseWithError(OpenStreamError, "") + _ = session.CloseWithError(OpenStreamError, "") return nil, serrors.WrapStr("opening stream", err) } return &acceptedConn{ diff --git a/pkg/sock/reliable/reconnect/conn.go b/pkg/sock/reliable/reconnect/conn.go index ab8695d35..866bc0629 100644 --- a/pkg/sock/reliable/reconnect/conn.go +++ b/pkg/sock/reliable/reconnect/conn.go @@ -21,6 +21,7 @@ import ( "time" "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/sock/reliable" ) @@ -152,8 +153,14 @@ func (conn *PacketConn) asyncReconnectWrapper() { close(conn.fatalError) return } - newConn.SetReadDeadline(conn.getReadDeadline()) - newConn.SetWriteDeadline(conn.getWriteDeadline()) + if err := serrors.Join( + newConn.SetReadDeadline(conn.getReadDeadline()), + newConn.SetWriteDeadline(conn.getWriteDeadline()), + ); err != nil { + conn.fatalError <- err + close(conn.fatalError) + return + } conn.setConn(newConn) conn.dispatcherState.SetUp() } @@ -197,7 +204,7 @@ func (conn *PacketConn) LocalAddr() net.Addr { func (conn *PacketConn) SetWriteDeadline(deadline time.Time) error { conn.writeDeadlineMtx.Lock() - conn.getConn().SetWriteDeadline(deadline) + err := conn.getConn().SetWriteDeadline(deadline) conn.writeDeadline = deadline select { case conn.deadlineChangedEvent <- struct{}{}: @@ -206,12 +213,12 @@ func (conn *PacketConn) SetWriteDeadline(deadline time.Time) error { // channel reader sees the new deadline. } conn.writeDeadlineMtx.Unlock() - return nil + return err } func (conn *PacketConn) SetReadDeadline(deadline time.Time) error { conn.readDeadlineMtx.Lock() - conn.getConn().SetReadDeadline(deadline) + err := conn.getConn().SetReadDeadline(deadline) conn.readDeadline = deadline select { case conn.deadlineChangedEvent <- struct{}{}: @@ -220,13 +227,14 @@ func (conn *PacketConn) SetReadDeadline(deadline time.Time) error { // channel reader sees the new deadline. } conn.readDeadlineMtx.Unlock() - return nil + return err } func (conn *PacketConn) SetDeadline(deadline time.Time) error { - conn.SetWriteDeadline(deadline) - conn.SetReadDeadline(deadline) - return nil + return serrors.Join( + conn.SetWriteDeadline(deadline), + conn.SetReadDeadline(deadline), + ) } func (conn *PacketConn) getDeadlineForOpType(op IOOperation) time.Time { diff --git a/pkg/sock/reliable/reliable.go b/pkg/sock/reliable/reliable.go index 3117c63e1..c70afac0b 100644 --- a/pkg/sock/reliable/reliable.go +++ b/pkg/sock/reliable/reliable.go @@ -193,7 +193,10 @@ func register(ctx context.Context, dispatcher string, ia addr.IA, public *net.UD // If a timeout was specified, make reads and writes return if deadline exceeded. if deadline, ok := ctx.Deadline(); ok { - conn.SetDeadline(deadline) + if err := conn.SetDeadline(deadline); err != nil { + resultChannel <- RegistrationReturn{err: err} + return + } } port, err := registrationExchange(conn, reg) @@ -216,8 +219,8 @@ func register(ctx context.Context, dispatcher string, ia addr.IA, public *net.UD "received", registrationReturn.port) } // Disable deadline to not affect future I/O - conn.SetDeadline(time.Time{}) - return conn, registrationReturn.port, nil + err = conn.SetDeadline(time.Time{}) + return conn, registrationReturn.port, err case <-ctx.Done(): // Unblock registration worker I/O conn.Close() @@ -276,7 +279,9 @@ func (conn *Conn) readFrom(buf []byte) (int, net.Addr, error) { return 0, nil, err } var p UnderlayPacket - p.DecodeFromBytes(conn.readBuffer[:n]) + if err := p.DecodeFromBytes(conn.readBuffer[:n]); err != nil { + return 0, nil, err + } var underlayAddr *net.UDPAddr if p.Address != nil { underlayAddr = &net.UDPAddr{ diff --git a/private/app/appnet/infraenv.go b/private/app/appnet/infraenv.go index 7f4acdab2..595cd1cc0 100644 --- a/private/app/appnet/infraenv.go +++ b/private/app/appnet/infraenv.go @@ -25,6 +25,7 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/pem" + "errors" "fmt" "math/big" "net" @@ -280,7 +281,16 @@ func (nc *NetworkConfig) initSvcRedirect(quicAddress string) (func(), error) { case <-done: return default: - conn.Read(buf) + // All the resolution logic is "hidden" in the + // svc.ResolverPacketDispatcher. Here, we just need to Read to + // drive this. Ignore errors from reading, just keep going. + _, err := conn.Read(buf) + if errors.Is(err, svc.ErrHandler) { + log.Debug("Error handling SVC request", "err", err) + } else if errors.Is(err, net.ErrClosed) { + log.Error("SVC resolution socket was closed", "err", err) + return + } } } }() diff --git a/private/app/launcher/launcher.go b/private/app/launcher/launcher.go index 7be6fa0e4..5a2aedb8f 100644 --- a/private/app/launcher/launcher.go +++ b/private/app/launcher/launcher.go @@ -121,7 +121,9 @@ func (a *Application) run() error { // The configuration file location is specified through command-line flags. // Once the comand-line flags are parsed, we register the location of the // config file with the viper config. - a.config.BindPFlag(cfgConfigFile, cmd.Flags().Lookup(cfgConfigFile)) + if err := a.config.BindPFlag(cfgConfigFile, cmd.Flags().Lookup(cfgConfigFile)); err != nil { + return err + } // All servers accept SIGTERM to perform clean shutdown (for example, this // is used behind the scenes by docker stop to cleanly shut down a container). diff --git a/private/app/path/pathprobe/paths.go b/private/app/path/pathprobe/paths.go index 3c3dcc16b..5a64f601c 100644 --- a/private/app/path/pathprobe/paths.go +++ b/private/app/path/pathprobe/paths.go @@ -203,7 +203,9 @@ func (p Prober) GetStatuses(ctx context.Context, paths []snet.Path, return serrors.WrapStr("creating packet conn", err, "local", localIP) } defer conn.Close() - conn.SetDeadline(deadline) + if err := conn.SetDeadline(deadline); err != nil { + return serrors.WrapStr("setting deadline", err) + } // Send probe for each path. for _, path := range paths { diff --git a/private/config/sample.go b/private/config/sample.go index 1f728872d..f6e0cddf6 100644 --- a/private/config/sample.go +++ b/private/config/sample.go @@ -26,7 +26,7 @@ import ( type CtxMap map[string]string // WriteSample writes all sample config blocks in order of appearance with -// indentation and header to dst. +// indentation and header to dst. It panics if an error occurs. func WriteSample(dst io.Writer, path Path, ctx CtxMap, samplers ...Sampler) { var buf bytes.Buffer for _, sampler := range samplers { @@ -39,7 +39,10 @@ func WriteSample(dst io.Writer, path Path, ctx CtxMap, samplers ...Sampler) { continue } sampler.Sample(&buf, path, ctx) - io.Copy(dst, &buf) + _, err := io.Copy(dst, &buf) + if err != nil { + panic(fmt.Sprintf("Unable to write sample err=%s", err)) + } } } diff --git a/private/mgmtapi/cppki/api/api.go b/private/mgmtapi/cppki/api/api.go index 58d2c3bd4..9082c5c68 100644 --- a/private/mgmtapi/cppki/api/api.go +++ b/private/mgmtapi/cppki/api/api.go @@ -20,7 +20,6 @@ import ( "encoding/json" "encoding/pem" "fmt" - "io" "net/http" "sort" "time" @@ -216,7 +215,7 @@ func (s *Server) GetCertificateBlob(w http.ResponseWriter, r *http.Request, chai return } } - io.Copy(w, &buf) + _, _ = w.Write(buf.Bytes()) } func (s *Server) GetTrcs(w http.ResponseWriter, r *http.Request, params GetTrcsParams) { @@ -378,5 +377,5 @@ func Error(w http.ResponseWriter, p Problem) { enc := json.NewEncoder(w) enc.SetIndent("", " ") // no point in catching error here, there is nothing we can do about it anymore. - enc.Encode(p) + _ = enc.Encode(p) } diff --git a/private/mgmtapi/segments/api/api.go b/private/mgmtapi/segments/api/api.go index f8610f4e6..216284ef5 100644 --- a/private/mgmtapi/segments/api/api.go +++ b/private/mgmtapi/segments/api/api.go @@ -21,7 +21,6 @@ import ( "encoding/json" "encoding/pem" "fmt" - "io" "net/http" "sort" @@ -234,7 +233,7 @@ func (s *Server) GetSegmentBlob(w http.ResponseWriter, r *http.Request, segmentI }) return } - io.Copy(w, &buf) + _, _ = w.Write(buf.Bytes()) } // SegID makes a hex encoded string of the segment id. @@ -247,5 +246,5 @@ func Error(w http.ResponseWriter, p Problem) { enc := json.NewEncoder(w) enc.SetIndent("", " ") // no point in catching error here, there is nothing we can do about it anymore. - enc.Encode(p) + _ = enc.Encode(p) } diff --git a/private/path/combinator/combinator.go b/private/path/combinator/combinator.go index 15bd546c7..14b15d8ba 100644 --- a/private/path/combinator/combinator.go +++ b/private/path/combinator/combinator.go @@ -138,8 +138,12 @@ func filterDuplicates(paths []Path) []Path { func fingerprint(interfaces []snet.PathInterface) snet.PathFingerprint { h := sha256.New() for _, intf := range interfaces { - binary.Write(h, binary.BigEndian, intf.IA) - binary.Write(h, binary.BigEndian, intf.ID) + if err := binary.Write(h, binary.BigEndian, intf.IA); err != nil { + panic(err) + } + if err := binary.Write(h, binary.BigEndian, intf.ID); err != nil { + panic(err) + } } return snet.PathFingerprint(h.Sum(nil)) } diff --git a/private/revcache/revcachetest/BUILD.bazel b/private/revcache/revcachetest/BUILD.bazel index cbd076971..709fba132 100644 --- a/private/revcache/revcachetest/BUILD.bazel +++ b/private/revcache/revcachetest/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "//pkg/private/xtest:go_default_library", "//private/revcache:go_default_library", "@com_github_smartystreets_goconvey//convey:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", ], ) diff --git a/private/revcache/revcachetest/revcachetest.go b/private/revcache/revcachetest/revcachetest.go index 01764533f..96ba9f638 100644 --- a/private/revcache/revcachetest/revcachetest.go +++ b/private/revcache/revcachetest/revcachetest.go @@ -21,6 +21,7 @@ import ( "time" . "github.com/smartystreets/goconvey/convey" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/scionproto/scion/pkg/addr" @@ -269,7 +270,8 @@ func testGetMuliKeysExpired(t *testing.T, revCache TestableRevCache) { } revCache.InsertExpired(t, ctx, revNew) rev110_19 := defaultRevInfo(ia110, ifId19) - revCache.Insert(ctx, rev110_19) + _, err := revCache.Insert(ctx, rev110_19) + assert.NoError(t, err) validKey := *revcache.NewKey(ia110, ifId19) srCache, err := revCache.Get(ctx, revcache.KeySet{ *revcache.NewKey(ia110, ifId15): {}, @@ -287,7 +289,8 @@ func testDeleteExpired(t *testing.T, revCache TestableRevCache) { SoMsg("DeleteExpired on empty should not error", err, ShouldBeNil) SoMsg("DeleteExpired on empty should delete 0", del, ShouldEqual, 0) rev110_19 := defaultRevInfo(ia110, ifId19) - revCache.Insert(ctx, rev110_19) + _, err = revCache.Insert(ctx, rev110_19) + assert.NoError(t, err) del, err = revCache.DeleteExpired(ctx) SoMsg("DeleteExpired should not error", err, ShouldBeNil) SoMsg("DeleteExpired should delete 0 if entry is not expired", del, ShouldEqual, 0) diff --git a/private/service/statuspages.go b/private/service/statuspages.go index 3e6de3279..73882c5c0 100644 --- a/private/service/statuspages.go +++ b/private/service/statuspages.go @@ -127,9 +127,13 @@ func (s StatusPages) Register(serveMux *http.ServeMux, elemId string) error { // NewConfigStatusPage returns a page with the specified TOML config. func NewConfigStatusPage(config interface{}) StatusPage { handler := func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/plain") var buf bytes.Buffer - toml.NewEncoder(&buf).Order(toml.OrderPreserve).Encode(config) + err := toml.NewEncoder(&buf).Order(toml.OrderPreserve).Encode(config) + if err != nil { + http.Error(w, "Error encoding toml config", http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, buf.String()) } return StatusPage{ diff --git a/private/storage/trust/fspersister/db_test.go b/private/storage/trust/fspersister/db_test.go index 2a9eb6106..94f54363e 100644 --- a/private/storage/trust/fspersister/db_test.go +++ b/private/storage/trust/fspersister/db_test.go @@ -125,7 +125,7 @@ func TestInsertTRCWithFSPersistence(t *testing.T) { t.Run("insert TRC not present in DB but present on FS", func(t *testing.T) { SignedTRC, persistedTrcPath := getTRC(t, "ISD2-B1-S1.trc", testDB.Dir) - os.WriteFile(persistedTrcPath, SignedTRC.Raw, 0644) + require.NoError(t, os.WriteFile(persistedTrcPath, SignedTRC.Raw, 0644)) mtimeBeforeInsert := getModTime(t, persistedTrcPath) in, err := testDB.InsertTRC(ctx, SignedTRC) diff --git a/private/svc/internal/ctxconn/ctxconn.go b/private/svc/internal/ctxconn/ctxconn.go index dec707d87..b1c3a142c 100644 --- a/private/svc/internal/ctxconn/ctxconn.go +++ b/private/svc/internal/ctxconn/ctxconn.go @@ -41,7 +41,9 @@ type CancelFunc func() // safe to call the returned function multiple times at the same time. func CloseConnOnDone(ctx context.Context, conn DeadlineCloser) CancelFunc { if deadline, ok := ctx.Deadline(); ok { - conn.SetDeadline(deadline) + // ignore error; if deadline cannot be set, we'll just close the conn + // when the context is Done anyway. + _ = conn.SetDeadline(deadline) } cancelSignal := make(chan struct{}) diff --git a/private/trust/db_inspector.go b/private/trust/db_inspector.go index 1e37f1b46..f2f50a42d 100644 --- a/private/trust/db_inspector.go +++ b/private/trust/db_inspector.go @@ -189,7 +189,7 @@ func (i CachingInspector) cacheAdd(key string, value interface{}, d time.Duratio if i.Cache == nil { return } - i.Cache.Add(key, value, d) + i.Cache.Add(key, value, d) //nolint:errcheck // XXX(matzf): could use Set, subtle difference } func (i CachingInspector) cacheExpiration() time.Duration { diff --git a/private/trust/verifier.go b/private/trust/verifier.go index 7b61db632..2c8946192 100644 --- a/private/trust/verifier.go +++ b/private/trust/verifier.go @@ -181,7 +181,7 @@ func (v *Verifier) cacheAdd(key string, value interface{}, d time.Duration) { if v.Cache == nil { return } - v.Cache.Add(key, value, d) + v.Cache.Add(key, value, d) //nolint:errcheck // XXX(matzf): could use Set, subtle difference } func (v *Verifier) cacheExpiration(chains [][]*x509.Certificate) time.Duration { diff --git a/private/trust/verifier_bench_test.go b/private/trust/verifier_bench_test.go index 1ff00fee6..6a3befa98 100644 --- a/private/trust/verifier_bench_test.go +++ b/private/trust/verifier_bench_test.go @@ -70,7 +70,8 @@ func BenchmarkConcurrent10(b *testing.B) { for j := 0; j < 10; j++ { go func() { defer wg.Done() - verifier.Verify(context.Background(), msg, associated...) + _, err := verifier.Verify(context.Background(), msg, associated...) + require.NoError(b, err) }() } wg.Wait() @@ -113,7 +114,8 @@ func BenchmarkConcurrentCache10(b *testing.B) { for j := 0; j < 10; j++ { go func() { defer wg.Done() - verifier.Verify(context.Background(), msg, associated...) + _, err := verifier.Verify(context.Background(), msg, associated...) + require.NoError(b, err) }() } wg.Wait() diff --git a/private/worker/BUILD.bazel b/private/worker/BUILD.bazel index cbe701276..cee1d4d7c 100644 --- a/private/worker/BUILD.bazel +++ b/private/worker/BUILD.bazel @@ -16,5 +16,6 @@ go_test( "//pkg/private/xtest:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", + "@org_golang_x_sync//errgroup:go_default_library", ], ) diff --git a/private/worker/worker_test.go b/private/worker/worker_test.go index dc13a3ec1..cf1ef2dc9 100644 --- a/private/worker/worker_test.go +++ b/private/worker/worker_test.go @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/private/worker" @@ -31,24 +32,26 @@ func TestWorker(t *testing.T) { t.Parallel() worker := &testWorker{} - go func() { - worker.Run() - }() + var bg errgroup.Group + bg.Go(worker.Run) time.Sleep(50 * time.Millisecond) err := worker.Run() assert.Error(t, err) + assert.NoError(t, worker.Close()) + assert.NoError(t, bg.Wait()) }) t.Run("double run nil worker", func(t *testing.T) { t.Parallel() worker := &nilTestWorker{} - go func() { - worker.Run() - }() + var bg errgroup.Group + bg.Go(worker.Run) time.Sleep(50 * time.Millisecond) err := worker.Run() assert.Error(t, err) + assert.NoError(t, worker.Close()) + assert.NoError(t, bg.Wait()) }) t.Run("close before run", func(t *testing.T) { diff --git a/router/bfd/BUILD.bazel b/router/bfd/BUILD.bazel index eb684bb82..4bd8fae56 100644 --- a/router/bfd/BUILD.bazel +++ b/router/bfd/BUILD.bazel @@ -26,7 +26,6 @@ go_test( "export_test.go", "fsm_test.go", "jitter_test.go", - "main_test.go", "metrics_test.go", "session_test.go", ], diff --git a/router/bfd/main_test.go b/router/bfd/main_test.go deleted file mode 100644 index 66b2c1b72..000000000 --- a/router/bfd/main_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 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 bfd_test - -import ( - "os" - "testing" - - "github.com/scionproto/scion/pkg/log/testlog" -) - -func TestMain(m *testing.M) { - // TODO(sustrik): This test is failing once in a while but the problem is almost impossible - // to reproduce. This way we'll at least have better understanding on what's going on. - testlog.SetupGlobal() - - os.Exit(m.Run()) -} diff --git a/router/dataplane_test.go b/router/dataplane_test.go index 4ae857cb9..34ddf66aa 100644 --- a/router/dataplane_test.go +++ b/router/dataplane_test.go @@ -1269,7 +1269,7 @@ func prepEpicMsg(t *testing.T, afterProcessing bool, key []byte, PHVF: make([]byte, 4), LHVF: make([]byte, 4), } - spkt.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("10.0.200.200").To4()}) + require.NoError(t, spkt.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("10.0.200.200").To4()})) spkt.Path = epicpath return spkt, epicpath, dpath diff --git a/router/export_test.go b/router/export_test.go index aab6031ff..f09660947 100644 --- a/router/export_test.go +++ b/router/export_test.go @@ -48,7 +48,9 @@ func NewDP( svc: &services{m: svc}, internal: internal, } - dp.SetKey(key) + if err := dp.SetKey(key); err != nil { + panic(err) + } return dp } diff --git a/router/mgmtapi/api.go b/router/mgmtapi/api.go index 74a00c417..f4b6ce5fd 100644 --- a/router/mgmtapi/api.go +++ b/router/mgmtapi/api.go @@ -155,5 +155,5 @@ func Error(w http.ResponseWriter, p Problem) { enc := json.NewEncoder(w) enc.SetIndent("", " ") // no point in catching error here, there is nothing we can do about it anymore. - enc.Encode(p) + _ = enc.Encode(p) } diff --git a/scion-pki/trcs/combine_test.go b/scion-pki/trcs/combine_test.go index 11566db0b..2be91d8e1 100644 --- a/scion-pki/trcs/combine_test.go +++ b/scion-pki/trcs/combine_test.go @@ -73,7 +73,7 @@ func TestCombine(t *testing.T) { }) raw, err := signed.Encode() require.NoError(t, err) - os.WriteFile("./testdata/admin/ISD1-B1-S1.trc", raw, 0644) + require.NoError(t, os.WriteFile("./testdata/admin/ISD1-B1-S1.trc", raw, 0644)) } dir, clean := xtest.MustTempDir("", "scion-pki-trcs-combine") diff --git a/tools/end2end/main.go b/tools/end2end/main.go index 5eb2cba5a..4db1e04f5 100644 --- a/tools/end2end/main.go +++ b/tools/end2end/main.go @@ -322,7 +322,9 @@ func (c *client) ping(ctx context.Context, n int, path snet.Path) error { if err != nil { return serrors.WrapStr("packing ping", err) } - c.conn.SetWriteDeadline(getDeadline(ctx)) + if err := c.conn.SetWriteDeadline(getDeadline(ctx)); err != nil { + return serrors.WrapStr("setting write deadline", err) + } if remote.NextHop == nil { remote.NextHop = &net.UDPAddr{ IP: remote.Host.IP, @@ -410,7 +412,9 @@ func (c *client) getRemote(ctx context.Context, n int) (snet.Path, error) { } func (c *client) pong(ctx context.Context) error { - c.conn.SetReadDeadline(getDeadline(ctx)) + if err := c.conn.SetReadDeadline(getDeadline(ctx)); err != nil { + return serrors.WrapStr("setting read deadline", err) + } var p snet.Packet var ov net.UDPAddr if err := readFrom(c.conn, &p, &ov); err != nil { diff --git a/tools/end2end_integration/main.go b/tools/end2end_integration/main.go index 6c3b5883a..757d25238 100644 --- a/tools/end2end_integration/main.go +++ b/tools/end2end_integration/main.go @@ -150,7 +150,7 @@ func runTests(in integration.Integration, pairs []integration.IAPair) error { cleaner := func() { cancel() if waiter != nil { - waiter.Wait() + _ = waiter.Wait() } } srvResults <- srvResult{cleaner: cleaner, err: err} diff --git a/tools/integration/binary.go b/tools/integration/binary.go index 477f6cfca..6d4d8d2cb 100644 --- a/tools/integration/binary.go +++ b/tools/integration/binary.go @@ -243,13 +243,13 @@ func (bi *binaryIntegration) writeLog(name, id, startInfo string, ep io.Reader) } w := bufio.NewWriter(f) defer w.Flush() - w.WriteString(WithTimestamp(fmt.Sprintf("Starting %s %s\n", name, startInfo))) + fmt.Fprintln(w, WithTimestamp(fmt.Sprintf("Starting %s %s", name, startInfo))) defer func() { - w.WriteString(WithTimestamp(fmt.Sprintf("Finished %s %s\n", name, startInfo))) + fmt.Fprintln(w, WithTimestamp(fmt.Sprintf("Finished %s %s", name, startInfo))) }() scanner := bufio.NewScanner(ep) for scanner.Scan() { - w.WriteString(fmt.Sprintf("%s\n", scanner.Text())) + fmt.Fprintln(w, scanner.Text()) } } diff --git a/tools/integration/done.go b/tools/integration/done.go index 17eea399a..33263377f 100644 --- a/tools/integration/done.go +++ b/tools/integration/done.go @@ -47,7 +47,9 @@ func ListenDone(dir string, onDone func(src, dst addr.IA)) (string, func(), erro srv := progress.Server{OnDone: onDone} go func() { defer log.HandlePanic() - srv.Serve(l) + if err := srv.Serve(l); err != nil { + log.Error("listening for done signals", "err", err) + } }() return name, func() { os.Remove(name) }, nil } diff --git a/tools/integration/integration.go b/tools/integration/integration.go index 244622eb4..991b708e7 100644 --- a/tools/integration/integration.go +++ b/tools/integration/integration.go @@ -282,8 +282,7 @@ type serverStop struct { func (s *serverStop) Close() error { s.cancel() - s.wait.Wait() - return nil + return s.wait.Wait() } // WithTimestamp returns s with the now timestamp prefixed. diff --git a/tools/integration/progress/progress.go b/tools/integration/progress/progress.go index 993d40d15..cfd81ba6a 100644 --- a/tools/integration/progress/progress.go +++ b/tools/integration/progress/progress.go @@ -64,7 +64,9 @@ type Server struct { // Serve starts serving the RPCs. func (s *Server) Serve(l net.Listener) error { - rpc.Register(&RPC{onDone: s.OnDone}) + if err := rpc.Register(&RPC{onDone: s.OnDone}); err != nil { + return err + } rpc.HandleHTTP() return http.Serve(l, nil) } From 91b6a48de72429d5a807e19a4d4ac2e6d3a49cbe Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Mon, 13 Feb 2023 10:58:46 +0100 Subject: [PATCH 007/255] seg: fix AddASEntry with multiple PeerEntries (#4315) During creating the signed protobuf body for an ASEntry in PathSegment.AddASentry, a reference to a member of the loop variable (`peer.HopField.MAC[:]`) was stored into newly created protobuf PeerEntries. As a result, all protobuf PeerEntries ended up with the same Mac buffer reference. Fixed by the usual `peer := peer`. Add tests for the case of multiple peers, both on the beacon extender and the path segment level. --- control/beaconing/extender_test.go | 33 ++++++++++++++++++++++-------- pkg/segment/seg.go | 1 + pkg/segment/seg_test.go | 27 ++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/control/beaconing/extender_test.go b/control/beaconing/extender_test.go index edf07d296..99163a683 100644 --- a/control/beaconing/extender_test.go +++ b/control/beaconing/extender_test.go @@ -47,19 +47,30 @@ func TestDefaultExtenderExtend(t *testing.T) { require.NoError(t, err) pub := priv.Public() - peer := graph.If_111_C_121_X + peerRemoteIfs := map[uint16]uint16{ + graph.If_111_C_121_X: graph.If_121_X_111_C, + graph.If_111_C_211_A: graph.If_211_A_111_C, + } testsCases := map[string]struct { ingress uint16 egress uint16 + peers []uint16 unsetPeers []uint16 errAssertion assert.ErrorAssertionFunc }{ "valid": { egress: graph.If_111_A_112_X, errAssertion: assert.NoError, + peers: []uint16{graph.If_111_C_121_X}, + }, + "two peers": { + egress: graph.If_111_A_112_X, + peers: []uint16{graph.If_111_C_121_X, graph.If_111_C_211_A}, + errAssertion: assert.NoError, }, "ignore unset peers": { egress: graph.If_111_A_112_X, + peers: []uint16{graph.If_111_C_121_X, graph.If_111_C_211_A}, unsetPeers: []uint16{graph.If_111_B_211_A}, errAssertion: assert.NoError, }, @@ -83,7 +94,9 @@ func TestDefaultExtenderExtend(t *testing.T) { defer mctrl.Finish() // Setup interfaces with active parent, child and one peer interface. intfs := ifstate.NewInterfaces(interfaceInfos(topo), ifstate.Config{}) - intfs.Get(peer).Activate(graph.If_121_X_111_C) + for _, peer := range tc.peers { + intfs.Get(peer).Activate(peerRemoteIfs[peer]) + } ext := &beaconing.DefaultExtender{ IA: topo.IA(), Signer: testSigner(t, priv, topo.IA()), @@ -97,12 +110,12 @@ func TestDefaultExtenderExtend(t *testing.T) { MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime }, StaticInfo: func() *beaconing.StaticInfoCfg { return nil }, } - pseg, err := seg.CreateSegment(time.Now(), uint16(mrand.Int())) + pseg, err := seg.CreateSegment(time.Time{}, 0) require.NoError(t, err) // Extend the segment. err = ext.Extend(context.Background(), pseg, tc.ingress, tc.egress, - append(tc.unsetPeers, peer)) + append(tc.peers, tc.unsetPeers...)) tc.errAssertion(t, err) if err != nil { return @@ -134,7 +147,7 @@ func TestDefaultExtenderExtend(t *testing.T) { assert.Equal(t, topo.IA(), entry.Local) assert.Equal(t, ia, entry.Next) // Checks that unset peers are ignored, even when provided. - assert.Len(t, entry.PeerEntries, 1) + assert.Len(t, entry.PeerEntries, len(tc.peers)) }) t.Run("hop entry check", func(t *testing.T) { assert.Equal(t, tc.ingress, entry.HopEntry.HopField.ConsIngress) @@ -143,10 +156,12 @@ func TestDefaultExtenderExtend(t *testing.T) { // FIXME(roosd): Check hop field can be authenticated. }) t.Run("peer entry check", func(t *testing.T) { - assert.Equal(t, peer, entry.PeerEntries[0].HopField.ConsIngress) - assert.Equal(t, tc.egress, entry.PeerEntries[0].HopField.ConsEgress) - assert.Equal(t, ext.MaxExpTime(), entry.PeerEntries[0].HopField.ExpTime) - // FIXME(roosd): Check hop field can be authenticated. + for i := range tc.peers { + assert.Equal(t, tc.peers[i], entry.PeerEntries[i].HopField.ConsIngress) + assert.Equal(t, tc.egress, entry.PeerEntries[i].HopField.ConsEgress) + assert.Equal(t, ext.MaxExpTime(), entry.PeerEntries[i].HopField.ExpTime) + // FIXME(roosd): Check hop field can be authenticated. + } }) }) } diff --git a/pkg/segment/seg.go b/pkg/segment/seg.go index a1c7d8ce3..ecc0467bf 100644 --- a/pkg/segment/seg.go +++ b/pkg/segment/seg.go @@ -276,6 +276,7 @@ func (ps *PathSegment) AddASEntry(ctx context.Context, asEntry ASEntry, signer S Extensions: extensionsToPB(asEntry.Extensions), } for _, peer := range asEntry.PeerEntries { + peer := peer asEntryPB.PeerEntries = append(asEntryPB.PeerEntries, &cppb.PeerEntry{ PeerIsdAs: uint64(peer.Peer), diff --git a/pkg/segment/seg_test.go b/pkg/segment/seg_test.go index 6c48eb429..7c8dd9a09 100644 --- a/pkg/segment/seg_test.go +++ b/pkg/segment/seg_test.go @@ -39,6 +39,8 @@ var ( as111 = xtest.MustParseIA("1-ff00:0:111") as112 = xtest.MustParseIA("1-ff00:0:112") as113 = xtest.MustParseIA("1-ff00:0:113") + as211 = xtest.MustParseIA("2-ff00:0:211") + as311 = xtest.MustParseIA("3-ff00:0:311") ) func TestPathSegmentAddASEntry(t *testing.T) { @@ -84,6 +86,29 @@ func TestPathSegmentAddASEntry(t *testing.T) { }, IngressMTU: 1442, }, + PeerEntries: []PeerEntry{ + { + Peer: as211, + PeerInterface: 2112, + PeerMTU: 1501, + HopField: HopField{ + ConsIngress: 1221, + ConsEgress: 21, + ExpTime: 60, + MAC: [path.MacLen]byte{0x44, 0x44, 0x44, 0x44, 0x44, 0x44}, + }, + }, { + Peer: as311, + PeerInterface: 3112, + PeerMTU: 1502, + HopField: HopField{ + ConsIngress: 1231, + ConsEgress: 21, + ExpTime: 59, + MAC: [path.MacLen]byte{0x55, 0x55, 0x55, 0x55, 0x55, 0x55}, + }, + }, + }, }, } var keyPairs []keyPair @@ -103,6 +128,7 @@ func TestPathSegmentAddASEntry(t *testing.T) { newID, newFullID := ps.ID(), ps.FullID() assert.NotEqual(t, id, newID) assert.NotEqual(t, fullID, newFullID) + } for i, kp := range keyPairs { @@ -112,6 +138,7 @@ func TestPathSegmentAddASEntry(t *testing.T) { c, err := BeaconFromPB(PathSegmentToPB(ps)) require.NoError(t, err) + assert.Equal(t, c, ps) for i, kp := range keyPairs { err := c.VerifyASEntry(context.Background(), kp, i) require.NoErrorf(t, err, "index: %d", i) From 18986094e9060e035604fd86c67152a9df8f59b1 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Mon, 13 Feb 2023 12:24:16 +0100 Subject: [PATCH 008/255] control: close connection in SVC resolver (#4314) When performing a service address resolution with svc.Resolver.LookupSVC, a new connection was opened but never closed. One possible reason for this bug was that the unclear responsibility for closing the connection; the svc.RoundTripper.RoundTrip function closes the connection if the context ends, but not otherwise. Fix this by always closing the conn in CloseConnOnDone. The cancel function of CloseConnOnDone now also blocks until the connection is closed (relevant mostly for testing) and returns any errors from closing. Also move the CloseConnOnDone to LookupSVC, so the responsibility for closing the connection is right next to where it's opened. --- private/svc/BUILD.bazel | 1 + private/svc/internal/ctxconn/ctxconn.go | 34 ++++++------------ private/svc/internal/ctxconn/ctxconn_test.go | 38 +++++++++++++------- private/svc/resolver.go | 10 ++++-- private/svc/resolver_test.go | 1 + 5 files changed, 45 insertions(+), 39 deletions(-) diff --git a/private/svc/BUILD.bazel b/private/svc/BUILD.bazel index 377aaf663..4d6724127 100644 --- a/private/svc/BUILD.bazel +++ b/private/svc/BUILD.bazel @@ -11,6 +11,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/addr:go_default_library", + "//pkg/log:go_default_library", "//pkg/private/common:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/proto/control_plane:go_default_library", diff --git a/private/svc/internal/ctxconn/ctxconn.go b/private/svc/internal/ctxconn/ctxconn.go index b1c3a142c..83f8531ee 100644 --- a/private/svc/internal/ctxconn/ctxconn.go +++ b/private/svc/internal/ctxconn/ctxconn.go @@ -29,41 +29,27 @@ type DeadlineCloser interface { io.Closer } -// CancelFunc can be used to shut down context watchers. It is safe to call the -// cancel function multiple times. -type CancelFunc func() - // CloseConnOnDone closes conn whenever ctx is Done. This includes if ctx is // canceled via its cancellation function. // -// Call the returned cancellation function to free up resources. Calling this -// function does not guarantee that the connection has been closed. It is not -// safe to call the returned function multiple times at the same time. -func CloseConnOnDone(ctx context.Context, conn DeadlineCloser) CancelFunc { +// Call the returned cancellation function to free up resources and closing the +// connection. The cancellation function returns any error from closing the connection. +func CloseConnOnDone(ctx context.Context, conn DeadlineCloser) func() error { if deadline, ok := ctx.Deadline(); ok { // ignore error; if deadline cannot be set, we'll just close the conn // when the context is Done anyway. _ = conn.SetDeadline(deadline) } - cancelSignal := make(chan struct{}) + ctx, cancelCtx := context.WithCancel(ctx) + errChan := make(chan error) go func() { defer log.HandlePanic() - select { - case <-ctx.Done(): - if err := conn.Close(); err != nil { - log.Info("Error closing conn when ctx canceled", "err", err) - } - case <-cancelSignal: - // shut down goroutine, free up resources - return - } + <-ctx.Done() + errChan <- conn.Close() }() - return func() { - select { - case <-cancelSignal: - default: - close(cancelSignal) - } + return func() error { + cancelCtx() + return <-errChan } } diff --git a/private/svc/internal/ctxconn/ctxconn_test.go b/private/svc/internal/ctxconn/ctxconn_test.go index 0f362a5de..bc9d31931 100644 --- a/private/svc/internal/ctxconn/ctxconn_test.go +++ b/private/svc/internal/ctxconn/ctxconn_test.go @@ -16,6 +16,7 @@ package ctxconn import ( "context" + "errors" "testing" "time" @@ -25,15 +26,26 @@ import ( "github.com/scionproto/scion/private/svc/internal/ctxconn/mock_ctxconn" ) -const baseUnit = time.Millisecond - func TestCloseConeOnDone(t *testing.T) { - t.Run("if no deadline and no ctx canceled, close it not called", func(t *testing.T) { + t.Run("if no deadline and no ctx canceled, close is called once", func(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - cancelFunc := CloseConnOnDone(context.Background(), nil) - assert.NotPanics(t, func() { cancelFunc() }) + closer := mock_ctxconn.NewMockDeadlineCloser(ctrl) + closer.EXPECT().Close() + cancelFunc := CloseConnOnDone(context.Background(), closer) + err := cancelFunc() + assert.NoError(t, err) + }) + t.Run("close error is returned", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + closer := mock_ctxconn.NewMockDeadlineCloser(ctrl) + testErr := errors.New("test") + closer.EXPECT().Close().Return(testErr) + cancelFunc := CloseConnOnDone(context.Background(), closer) + err := cancelFunc() + assert.Equal(t, testErr, err) }) t.Run("if no deadline and ctx canceled, close is called once", func(t *testing.T) { ctrl := gomock.NewController(t) @@ -43,20 +55,22 @@ func TestCloseConeOnDone(t *testing.T) { closer := mock_ctxconn.NewMockDeadlineCloser(ctrl) closer.EXPECT().Close() cancelFunc := CloseConnOnDone(ctx, closer) - time.Sleep(20 * baseUnit) - cancelFunc() + err := cancelFunc() + assert.NoError(t, err) }) t.Run("if deadline expires, close is called once", func(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - deadline := time.Now().Add(0) - ctx, cancelF := context.WithDeadline(context.Background(), deadline) - defer cancelF() + deadline := time.Now().Add(20 * time.Millisecond) + ctx, ctxCancelF := context.WithDeadline(context.Background(), deadline) + closer := mock_ctxconn.NewMockDeadlineCloser(ctrl) closer.EXPECT().Close() closer.EXPECT().SetDeadline(deadline) - CloseConnOnDone(ctx, closer) - time.Sleep(20 * baseUnit) + cancelFunc := CloseConnOnDone(ctx, closer) + ctxCancelF() // Pretend that we hit the deadline + err := cancelFunc() + assert.NoError(t, err) }) } diff --git a/private/svc/resolver.go b/private/svc/resolver.go index cb21d1f28..ad0c2190c 100644 --- a/private/svc/resolver.go +++ b/private/svc/resolver.go @@ -23,6 +23,7 @@ import ( "google.golang.org/protobuf/proto" "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/serrors" cppb "github.com/scionproto/scion/pkg/proto/control_plane" @@ -83,6 +84,12 @@ func (r *Resolver) LookupSVC(ctx context.Context, p snet.Path, svc addr.HostSVC) ext.Error.Set(span, true) return nil, serrors.Wrap(errRegistration, err) } + cancelF := ctxconn.CloseConnOnDone(ctx, conn) + defer func() { + if err := cancelF(); err != nil { + log.Info("Error closing conn", "err", err) + } + }() requestPacket := &snet.Packet{ PacketInfo: snet.PacketInfo{ @@ -137,9 +144,6 @@ type roundTripper struct{} func (roundTripper) RoundTrip(ctx context.Context, c snet.PacketConn, pkt *snet.Packet, u *net.UDPAddr) (*Reply, error) { - cancelF := ctxconn.CloseConnOnDone(ctx, c) - defer cancelF() - if pkt == nil { return nil, errNilPacket } diff --git a/private/svc/resolver_test.go b/private/svc/resolver_test.go index 926d86826..72325863e 100644 --- a/private/svc/resolver_test.go +++ b/private/svc/resolver_test.go @@ -68,6 +68,7 @@ func TestResolver(t *testing.T) { mockPacketDispatcherService.EXPECT().Register(gomock.Any(), srcIA, &net.UDPAddr{IP: net.IP{192, 0, 2, 1}}, addr.SvcNone).Return(mockConn, uint16(42), nil) + mockConn.EXPECT().Close() mockRoundTripper := mock_svc.NewMockRoundTripper(ctrl) mockRoundTripper.EXPECT().RoundTrip(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Do( From 5cb963057bed31ffd470a1ec3a915333352652c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 10:41:42 +0100 Subject: [PATCH 009/255] deps: bump github.com/prometheus/client_golang from 1.11.0 to 1.11.1 (#4316) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.11.0 to 1.11.1. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.11.0...v1.11.1) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production ... Signed-off-by: dependabot[bot] * fixup: make go_deps.bzl --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matthias Frei --- go.mod | 2 +- go.sum | 3 ++- go_deps.bzl | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 970649e36..fc37aa9a8 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/patrickmn/go-cache v2.1.1-0.20180815053127-5633e0862627+incompatible github.com/pelletier/go-toml v1.9.4 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.11.0 + github.com/prometheus/client_golang v1.11.1 github.com/sergi/go-diff v1.2.0 github.com/smartystreets/goconvey v1.6.7 github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b diff --git a/go.sum b/go.sum index 4395d1870..3a2225e7e 100644 --- a/go.sum +++ b/go.sum @@ -425,8 +425,9 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/go_deps.bzl b/go_deps.bzl index fa9336e11..08bc34dcb 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -1103,8 +1103,8 @@ def go_deps(): go_repository( name = "com_github_prometheus_client_golang", importpath = "github.com/prometheus/client_golang", - sum = "h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=", - version = "v1.11.0", + sum = "h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s=", + version = "v1.11.1", ) go_repository( name = "com_github_prometheus_client_model", From 3318edbf50c7a9e79e3d11607805922b15466273 Mon Sep 17 00:00:00 2001 From: Marc Frei Date: Thu, 16 Feb 2023 16:08:59 +0100 Subject: [PATCH 010/255] pkt/spao: support empty path value as input for SPAO MAC computation (#4317) Implement support for empty path values as inputs for the SPAO MAC computation. This is currently not applicable when using the SPAO with DRKey as the timestamp defined to be relative to the info field, which simply does not exist for empty paths. This will be addressed by the changes proposed in scionproto/scion#4300, enabling the use of SPAO also for AS internal communication. --- pkg/spao/BUILD.bazel | 2 ++ pkg/spao/mac.go | 3 +++ pkg/spao/mac_test.go | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/pkg/spao/BUILD.bazel b/pkg/spao/BUILD.bazel index c7ce25057..f047fd0e4 100644 --- a/pkg/spao/BUILD.bazel +++ b/pkg/spao/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "//pkg/private/util:go_default_library", "//pkg/slayers:go_default_library", "//pkg/slayers/path:go_default_library", + "//pkg/slayers/path/empty:go_default_library", "//pkg/slayers/path/epic:go_default_library", "//pkg/slayers/path/onehop:go_default_library", "//pkg/slayers/path/scion:go_default_library", @@ -34,6 +35,7 @@ go_test( "//pkg/private/xtest:go_default_library", "//pkg/slayers:go_default_library", "//pkg/slayers/path:go_default_library", + "//pkg/slayers/path/empty:go_default_library", "//pkg/slayers/path/epic:go_default_library", "//pkg/slayers/path/onehop:go_default_library", "//pkg/slayers/path/scion:go_default_library", diff --git a/pkg/spao/mac.go b/pkg/spao/mac.go index 7daf09c41..4c963e10e 100644 --- a/pkg/spao/mac.go +++ b/pkg/spao/mac.go @@ -25,6 +25,7 @@ import ( "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/pkg/slayers/path/empty" "github.com/scionproto/scion/pkg/slayers/path/epic" "github.com/scionproto/scion/pkg/slayers/path/onehop" "github.com/scionproto/scion/pkg/slayers/path/scion" @@ -159,6 +160,8 @@ func zeroOutMutablePath(orig path.Path, buf []byte) error { return serrors.WrapStr("serializing path for resetting fields", err) } switch p := orig.(type) { + case empty.Path: + return nil case *scion.Raw: zeroOutWithBase(p.Base, buf) return nil diff --git a/pkg/spao/mac_test.go b/pkg/spao/mac_test.go index a54a891dc..504c90471 100644 --- a/pkg/spao/mac_test.go +++ b/pkg/spao/mac_test.go @@ -29,6 +29,7 @@ import ( "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/pkg/slayers/path/empty" "github.com/scionproto/scion/pkg/slayers/path/epic" "github.com/scionproto/scion/pkg/slayers/path/onehop" "github.com/scionproto/scion/pkg/slayers/path/scion" @@ -106,6 +107,41 @@ func TestComputeAuthMac(t *testing.T) { rawMACInput []byte assertErr assert.ErrorAssertionFunc }{ + "empty": { + optionParameter: slayers.PacketAuthOptionParams{ + SPI: slayers.PacketAuthSPI(0x1), + Algorithm: slayers.PacketAuthCMAC, + Timestamp: 0x3e8, + SequenceNumber: sn, + Auth: make([]byte, 16), + }, + scionL: slayers.SCION{ + FlowID: binary.BigEndian.Uint32([]byte{0x00, 0x00, 0x12, 0x34}), + TrafficClass: 0xff, + NextHdr: slayers.End2EndClass, + SrcIA: dstIA, + DstIA: dstIA, + SrcAddrType: slayers.T4Ip, + RawSrcAddr: net.IPv4(10, 1, 1, 11).To4(), + DstAddrType: slayers.T4Ip, + RawDstAddr: net.IPv4(10, 1, 1, 12).To4(), + Path: empty.Path{}, + PathType: empty.PathType, + }, + pld: fooPayload, + rawMACInput: append([]byte{ + // 1. Authenticator Option Metadata + 0x24, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length + 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp + 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number + // 2. SCION Common Header + 0x3, 0xf0, 0x12, 0x34, // Version | QoS | FlowID + 0x0, 0x0, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV + // 3. SCION Address Header + 0xa, 0x1, 0x1, 0xb, + }, fooPayload...), + assertErr: assert.NoError, + }, "decoded": { optionParameter: slayers.PacketAuthOptionParams{ SPI: slayers.PacketAuthSPI(0x1), @@ -304,13 +340,14 @@ func TestComputeAuthMac(t *testing.T) { assert.NoError(t, err) buf := make([]byte, spao.MACBufferSize) - inpLen, _ := spao.SerializeAuthenticatedData( + inpLen, err := spao.SerializeAuthenticatedData( buf, &tc.scionL, optAuth, slayers.L4SCMP, tc.pld, ) + require.NoError(t, err) require.Equal(t, tc.rawMACInput, append(buf[:inpLen], fooPayload...)) mac, err := spao.ComputeAuthCMAC( From fd821384375a300256c2b13aa49b43d5d634469b Mon Sep 17 00:00:00 2001 From: Marc Frei Date: Tue, 21 Feb 2023 10:24:14 +0100 Subject: [PATCH 011/255] pkt/spao: fix computation of header length metadata item (#4318) The length of the SCION header is part of the metadata flowing into the computation of the MAC value for SPAO [0]. The corresponding common header field value is stored in multiples of 4-bytes [1]. This PR makes sure that indeed multiples of 4-bytes are used instead of the actual length in bytes of the SCION header. The problem did not appear in testing up till now, because all endpoints are based on the same implementation so far. [0] https://docs.scion.org/en/latest/protocols/authenticator-option.html#authenticated-data [1] https://docs.scion.org/en/latest/protocols/scion-header.html#common-header --- pkg/spao/mac.go | 12 +++++++++++- pkg/spao/mac_test.go | 10 ++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pkg/spao/mac.go b/pkg/spao/mac.go index 4c963e10e..898cc4f26 100644 --- a/pkg/spao/mac.go +++ b/pkg/spao/mac.go @@ -113,7 +113,17 @@ func serializeAuthenticatedData( _ = buf[MACBufferSize-1] - buf[0] = byte(slayers.CmnHdrLen + s.AddrHdrLen() + s.Path.Len()) + hdrLen := slayers.CmnHdrLen + s.AddrHdrLen() + s.Path.Len() + if hdrLen > slayers.MaxHdrLen { + return 0, serrors.New("SCION header length exceeds maximum", + "max", slayers.MaxHdrLen, "actual", hdrLen) + } + if hdrLen%slayers.LineLen != 0 { + return 0, serrors.New("SCION header length is not an integer multiple of line length", + "actual", hdrLen) + } + + buf[0] = byte(hdrLen / slayers.LineLen) buf[1] = byte(pldType) binary.BigEndian.PutUint16(buf[2:], uint16(len(pld))) buf[4] = byte(opt.Algorithm()) diff --git a/pkg/spao/mac_test.go b/pkg/spao/mac_test.go index 504c90471..2d6a7e8f0 100644 --- a/pkg/spao/mac_test.go +++ b/pkg/spao/mac_test.go @@ -131,7 +131,7 @@ func TestComputeAuthMac(t *testing.T) { pld: fooPayload, rawMACInput: append([]byte{ // 1. Authenticator Option Metadata - 0x24, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length + 0x9, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number // 2. SCION Common Header @@ -166,7 +166,7 @@ func TestComputeAuthMac(t *testing.T) { pld: fooPayload, rawMACInput: append([]byte{ // 1. Authenticator Option Metadata - 0x70, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length + 0x1c, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number // 2. SCION Common Header @@ -206,7 +206,6 @@ func TestComputeAuthMac(t *testing.T) { Auth: make([]byte, 16), }, scionL: slayers.SCION{ - HdrLen: 255, FlowID: binary.BigEndian.Uint32([]byte{0x00, 0x00, 0x12, 0x34}), TrafficClass: 0xff, NextHdr: slayers.End2EndClass, @@ -243,7 +242,7 @@ func TestComputeAuthMac(t *testing.T) { pld: fooPayload, rawMACInput: append([]byte{ // 1. Authenticator Option Metadata - 0x44, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length + 0x11, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number // 2. SCION Common Header @@ -272,7 +271,6 @@ func TestComputeAuthMac(t *testing.T) { Auth: make([]byte, 16), }, scionL: slayers.SCION{ - HdrLen: 255, FlowID: binary.BigEndian.Uint32([]byte{0x00, 0x00, 0x12, 0x34}), TrafficClass: 0xff, NextHdr: slayers.End2EndClass, @@ -300,7 +298,7 @@ func TestComputeAuthMac(t *testing.T) { rawMACInput: append([]byte{ // 1. Authenticator Option Metadata - 0x74, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length + 0x1d, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number // 2. SCION Common Header From 2ab6125dc8c35544105e64df2f320b2ad85fb04e Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Wed, 22 Feb 2023 14:45:58 +0100 Subject: [PATCH 012/255] doc: fix conf and rst files to get clean build (#4319) Documentation builds (`make html`) were reporting various warnings. There were two sources of the errors: - Most pages from the autogenerated command line docs are not in any toctree, because they use their own internal linking. Fixed by adding :orphan: to these pages. - One image in the manual pages (gateway/prefix_pinning.rst) would always be reported as not found, but was working correctly. This was due to the structure of the manual pages, which are built from multiple partial rst files using the `.. include:` directive. The figures are found relative to the main rst file, not the partial. As the partials were _also_ being built individually, the error resulted. Fixed by excluding the partial rst files (manuals/*/*) from the sphinx build. Also includes the following improvements: - more specific short/long doc string for the `scion` tool - add requirements.in and pip-compile generated requirements.txt - doc/Makefile: add targets autobuild and command-gendocs for convenience, explicitly list the main sphinx-build targets to get make target auto-completion on shells - Disable the "Atuo generated by spf13/cobra ..." footer for the cobra gendocs, getting rid of post processing command in the bazel build. Use "proper" sphinx :ref: cross-references instead of html links. - Fix (or remove) some broken links reported by `make linkcheck` --- .gitignore | 1 + doc/Makefile | 35 ++- doc/build/setup.rst | 2 +- doc/command/BUILD.bazel | 2 - doc/command/scion-pki/scion-pki.rst | 12 +- .../scion-pki/scion-pki_certificate.rst | 20 +- .../scion-pki_certificate_create.rst | 4 +- .../scion-pki_certificate_fingerprint.rst | 4 +- .../scion-pki_certificate_inspect.rst | 6 +- .../scion-pki/scion-pki_certificate_match.rst | 6 +- .../scion-pki_certificate_match_private.rst | 4 +- .../scion-pki/scion-pki_certificate_renew.rst | 4 +- .../scion-pki/scion-pki_certificate_sign.rst | 4 +- .../scion-pki_certificate_validate.rst | 4 +- .../scion-pki_certificate_verify.rst | 6 +- .../scion-pki_certificate_verify_ca.rst | 4 +- .../scion-pki/scion-pki_completion.rst | 12 +- .../scion-pki/scion-pki_completion_bash.rst | 4 +- .../scion-pki/scion-pki_completion_fish.rst | 4 +- .../scion-pki_completion_powershell.rst | 4 +- .../scion-pki/scion-pki_completion_zsh.rst | 4 +- doc/command/scion-pki/scion-pki_key.rst | 14 +- .../scion-pki/scion-pki_key_fingerprint.rst | 4 +- doc/command/scion-pki/scion-pki_key_match.rst | 6 +- .../scion-pki_key_match_certificate.rst | 4 +- .../scion-pki/scion-pki_key_private.rst | 4 +- .../scion-pki/scion-pki_key_public.rst | 4 +- .../scion-pki/scion-pki_key_symmetric.rst | 4 +- doc/command/scion-pki/scion-pki_trc.rst | 18 +- .../scion-pki/scion-pki_trc_combine.rst | 4 +- .../scion-pki/scion-pki_trc_extract.rst | 8 +- .../scion-pki_trc_extract_certificates.rst | 4 +- .../scion-pki_trc_extract_payload.rst | 4 +- .../scion-pki/scion-pki_trc_format.rst | 4 +- .../scion-pki/scion-pki_trc_inspect.rst | 4 +- .../scion-pki/scion-pki_trc_payload.rst | 4 +- doc/command/scion-pki/scion-pki_trc_sign.rst | 4 +- .../scion-pki/scion-pki_trc_verify.rst | 4 +- doc/command/scion-pki/scion-pki_version.rst | 4 +- doc/command/scion/scion.rst | 18 +- doc/command/scion/scion_address.rst | 4 +- doc/command/scion/scion_completion.rst | 12 +- doc/command/scion/scion_completion_bash.rst | 4 +- doc/command/scion/scion_completion_fish.rst | 4 +- .../scion/scion_completion_powershell.rst | 4 +- doc/command/scion/scion_completion_zsh.rst | 4 +- doc/command/scion/scion_ping.rst | 4 +- doc/command/scion/scion_showpaths.rst | 4 +- doc/command/scion/scion_traceroute.rst | 4 +- doc/command/scion/scion_version.rst | 4 +- doc/conf.py | 10 +- doc/cryptography/certificates.rst | 7 - doc/index.rst | 11 +- doc/requirements.in | 4 + doc/requirements.txt | 294 +++++++++++++++++- doc/testing/mocks.rst | 2 +- scion-pki/certs/inspect.go | 2 +- scion-pki/cmd/scion-pki/gendocs.go | 4 +- scion-pki/cmd/scion-pki/main.go | 1 + scion/cmd/scion/gendocs.go | 4 +- scion/cmd/scion/main.go | 7 +- 61 files changed, 523 insertions(+), 137 deletions(-) mode change 100644 => 100755 doc/command/scion-pki/scion-pki.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate_create.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate_fingerprint.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate_inspect.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate_match.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate_match_private.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate_renew.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate_sign.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate_validate.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate_verify.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_certificate_verify_ca.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_completion.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_completion_bash.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_completion_fish.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_completion_powershell.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_completion_zsh.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_key.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_key_fingerprint.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_key_match.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_key_match_certificate.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_key_private.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_key_public.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_key_symmetric.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_trc.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_trc_combine.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_trc_extract.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_trc_extract_certificates.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_trc_extract_payload.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_trc_format.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_trc_inspect.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_trc_payload.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_trc_sign.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_trc_verify.rst mode change 100644 => 100755 doc/command/scion-pki/scion-pki_version.rst mode change 100644 => 100755 doc/command/scion/scion.rst mode change 100644 => 100755 doc/command/scion/scion_address.rst mode change 100644 => 100755 doc/command/scion/scion_completion.rst mode change 100644 => 100755 doc/command/scion/scion_completion_bash.rst mode change 100644 => 100755 doc/command/scion/scion_completion_fish.rst mode change 100644 => 100755 doc/command/scion/scion_completion_powershell.rst mode change 100644 => 100755 doc/command/scion/scion_completion_zsh.rst mode change 100644 => 100755 doc/command/scion/scion_ping.rst mode change 100644 => 100755 doc/command/scion/scion_showpaths.rst mode change 100644 => 100755 doc/command/scion/scion_traceroute.rst mode change 100644 => 100755 doc/command/scion/scion_version.rst create mode 100644 doc/requirements.in diff --git a/.gitignore b/.gitignore index 8429a0a95..fb8655189 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ compile_commands.json # Environment files ######################### /venv/ +doc/venv/ # Docker working directory ########################## diff --git a/doc/Makefile b/doc/Makefile index d4bb2cbb9..fc16ae624 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,20 +1,27 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. +# These variables can be overridden from the command line from the environment. SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +# Build docs with Sphinx using the "make mode" option. +# Explicitly list the main build targets so they auto-complete in shells. +# The first listed name is the default goal (i.e. `make` is `make html`). +.PHONY: html latex latexpdf linkcheck help +html latex latexpdf linkcheck help: + sphinx-build -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) + +# Catch-all pattern to match any unknown target, too. +.PHONY: % +%: + sphinx-build -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) -.PHONY: help Makefile +# Autobuild; automatically build HTML on source changes and serve on localhost +.PHONY: autobuild +autobuild: + sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +# Generate commandline docs by building the tools and running their `gendocus` subcommand +.PHONY: command-gendocs +command-gendocs: + bazel run //doc/command:copy_scion + bazel run //doc/command:copy_scion-pki diff --git a/doc/build/setup.rst b/doc/build/setup.rst index dbde66c4b..d35eebcfe 100644 --- a/doc/build/setup.rst +++ b/doc/build/setup.rst @@ -194,7 +194,7 @@ interface on a different machine. - For Ubuntu install as described in the steps above. - For MacOS and Windows just download & install from the `wireshark website - `_. + `_. #. Install dissector plugin diff --git a/doc/command/BUILD.bazel b/doc/command/BUILD.bazel index 0f25d4d49..07a2d41c8 100644 --- a/doc/command/BUILD.bazel +++ b/doc/command/BUILD.bazel @@ -7,14 +7,12 @@ exports_files( recursive_copy_output( name = "copy_scion", - file_transformation = "head -n -1 $FILE > temp.rst ; mv temp.rst $FILE", input_dir = "//scion/cmd/scion:gendocs", output_dir = ":scion", ) recursive_copy_output( name = "copy_scion-pki", - file_transformation = "head -n -1 $FILE > temp.rst ; mv temp.rst $FILE", input_dir = "//scion-pki/cmd/scion-pki:gendocs", output_dir = ":scion-pki", ) diff --git a/doc/command/scion-pki/scion-pki.rst b/doc/command/scion-pki/scion-pki.rst old mode 100644 new mode 100755 index 7c55db11c..a46874a65 --- a/doc/command/scion-pki/scion-pki.rst +++ b/doc/command/scion-pki/scion-pki.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki: scion-pki @@ -21,9 +23,9 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate `_ - Manage certificates for the SCION control plane PKI. -* `scion-pki completion `_ - Generate the autocompletion script for the specified shell -* `scion-pki key `_ - Manage private and public keys -* `scion-pki trc `_ - Manage TRCs for the SCION control plane PKI -* `scion-pki version `_ - Show the scion-pki version information +* :ref:`scion-pki certificate ` - Manage certificates for the SCION control plane PKI. +* :ref:`scion-pki completion ` - Generate the autocompletion script for the specified shell +* :ref:`scion-pki key ` - Manage private and public keys +* :ref:`scion-pki trc ` - Manage TRCs for the SCION control plane PKI +* :ref:`scion-pki version ` - Show the scion-pki version information diff --git a/doc/command/scion-pki/scion-pki_certificate.rst b/doc/command/scion-pki/scion-pki_certificate.rst old mode 100644 new mode 100755 index 715da0ff7..6a0084420 --- a/doc/command/scion-pki/scion-pki_certificate.rst +++ b/doc/command/scion-pki/scion-pki_certificate.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_certificate: scion-pki certificate @@ -21,13 +23,13 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki `_ - SCION Control Plane PKI Management Tool -* `scion-pki certificate create `_ - Create a certificate or certificate signing request -* `scion-pki certificate fingerprint `_ - Calculate the SHA256 fingerprint of a certificate or certificate chain -* `scion-pki certificate inspect `_ - Inspect a certificate or a certificate signing request -* `scion-pki certificate match `_ - Match the certificate with other trust objects -* `scion-pki certificate renew `_ - Renew an AS certificate -* `scion-pki certificate sign `_ - Sign a certificate based on a certificate signing request -* `scion-pki certificate validate `_ - Validate a SCION cert according to its type -* `scion-pki certificate verify `_ - Verify a certificate chain +* :ref:`scion-pki ` - SCION Control Plane PKI Management Tool +* :ref:`scion-pki certificate create ` - Create a certificate or certificate signing request +* :ref:`scion-pki certificate fingerprint ` - Calculate the SHA256 fingerprint of a certificate or certificate chain +* :ref:`scion-pki certificate inspect ` - Inspect a certificate or a certificate signing request +* :ref:`scion-pki certificate match ` - Match the certificate with other trust objects +* :ref:`scion-pki certificate renew ` - Renew an AS certificate +* :ref:`scion-pki certificate sign ` - Sign a certificate based on a certificate signing request +* :ref:`scion-pki certificate validate ` - Validate a SCION cert according to its type +* :ref:`scion-pki certificate verify ` - Verify a certificate chain diff --git a/doc/command/scion-pki/scion-pki_certificate_create.rst b/doc/command/scion-pki/scion-pki_certificate_create.rst old mode 100644 new mode 100755 index 94fff3e3c..fb97bcf46 --- a/doc/command/scion-pki/scion-pki_certificate_create.rst +++ b/doc/command/scion-pki/scion-pki_certificate_create.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_certificate_create: scion-pki certificate create @@ -123,5 +125,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate `_ - Manage certificates for the SCION control plane PKI. +* :ref:`scion-pki certificate ` - Manage certificates for the SCION control plane PKI. diff --git a/doc/command/scion-pki/scion-pki_certificate_fingerprint.rst b/doc/command/scion-pki/scion-pki_certificate_fingerprint.rst old mode 100644 new mode 100755 index 724cbe2ab..043e0eaba --- a/doc/command/scion-pki/scion-pki_certificate_fingerprint.rst +++ b/doc/command/scion-pki/scion-pki_certificate_fingerprint.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_certificate_fingerprint: scion-pki certificate fingerprint @@ -43,5 +45,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate `_ - Manage certificates for the SCION control plane PKI. +* :ref:`scion-pki certificate ` - Manage certificates for the SCION control plane PKI. diff --git a/doc/command/scion-pki/scion-pki_certificate_inspect.rst b/doc/command/scion-pki/scion-pki_certificate_inspect.rst old mode 100644 new mode 100755 index 4f2516034..d252be359 --- a/doc/command/scion-pki/scion-pki_certificate_inspect.rst +++ b/doc/command/scion-pki/scion-pki_certificate_inspect.rst @@ -1,9 +1,11 @@ +:orphan: + .. _scion-pki_certificate_inspect: scion-pki certificate inspect ----------------------------- -Inspect a certificate or a certificate signing request +Inspect a certificate or a certificate signing request Synopsis ~~~~~~~~ @@ -35,5 +37,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate `_ - Manage certificates for the SCION control plane PKI. +* :ref:`scion-pki certificate ` - Manage certificates for the SCION control plane PKI. diff --git a/doc/command/scion-pki/scion-pki_certificate_match.rst b/doc/command/scion-pki/scion-pki_certificate_match.rst old mode 100644 new mode 100755 index 813a184c7..7ec30fbbf --- a/doc/command/scion-pki/scion-pki_certificate_match.rst +++ b/doc/command/scion-pki/scion-pki_certificate_match.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_certificate_match: scion-pki certificate match @@ -21,6 +23,6 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate `_ - Manage certificates for the SCION control plane PKI. -* `scion-pki certificate match private `_ - Find the matching private keys for the certificate +* :ref:`scion-pki certificate ` - Manage certificates for the SCION control plane PKI. +* :ref:`scion-pki certificate match private ` - Find the matching private keys for the certificate diff --git a/doc/command/scion-pki/scion-pki_certificate_match_private.rst b/doc/command/scion-pki/scion-pki_certificate_match_private.rst old mode 100644 new mode 100755 index b2dac8415..c9501438e --- a/doc/command/scion-pki/scion-pki_certificate_match_private.rst +++ b/doc/command/scion-pki/scion-pki_certificate_match_private.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_certificate_match_private: scion-pki certificate match private @@ -39,5 +41,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate match `_ - Match the certificate with other trust objects +* :ref:`scion-pki certificate match ` - Match the certificate with other trust objects diff --git a/doc/command/scion-pki/scion-pki_certificate_renew.rst b/doc/command/scion-pki/scion-pki_certificate_renew.rst old mode 100644 new mode 100755 index bb5cea6b3..e834c9f27 --- a/doc/command/scion-pki/scion-pki_certificate_renew.rst +++ b/doc/command/scion-pki/scion-pki_certificate_renew.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_certificate_renew: scion-pki certificate renew @@ -150,5 +152,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate `_ - Manage certificates for the SCION control plane PKI. +* :ref:`scion-pki certificate ` - Manage certificates for the SCION control plane PKI. diff --git a/doc/command/scion-pki/scion-pki_certificate_sign.rst b/doc/command/scion-pki/scion-pki_certificate_sign.rst old mode 100644 new mode 100755 index 6649003af..625ec980c --- a/doc/command/scion-pki/scion-pki_certificate_sign.rst +++ b/doc/command/scion-pki/scion-pki_certificate_sign.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_certificate_sign: scion-pki certificate sign @@ -71,5 +73,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate `_ - Manage certificates for the SCION control plane PKI. +* :ref:`scion-pki certificate ` - Manage certificates for the SCION control plane PKI. diff --git a/doc/command/scion-pki/scion-pki_certificate_validate.rst b/doc/command/scion-pki/scion-pki_certificate_validate.rst old mode 100644 new mode 100755 index d80141964..ddd1416eb --- a/doc/command/scion-pki/scion-pki_certificate_validate.rst +++ b/doc/command/scion-pki/scion-pki_certificate_validate.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_certificate_validate: scion-pki certificate validate @@ -49,5 +51,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate `_ - Manage certificates for the SCION control plane PKI. +* :ref:`scion-pki certificate ` - Manage certificates for the SCION control plane PKI. diff --git a/doc/command/scion-pki/scion-pki_certificate_verify.rst b/doc/command/scion-pki/scion-pki_certificate_verify.rst old mode 100644 new mode 100755 index c521bd280..c5a594d00 --- a/doc/command/scion-pki/scion-pki_certificate_verify.rst +++ b/doc/command/scion-pki/scion-pki_certificate_verify.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_certificate_verify: scion-pki certificate verify @@ -46,6 +48,6 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate `_ - Manage certificates for the SCION control plane PKI. -* `scion-pki certificate verify ca `_ - Verify a CA certificate +* :ref:`scion-pki certificate ` - Manage certificates for the SCION control plane PKI. +* :ref:`scion-pki certificate verify ca ` - Verify a CA certificate diff --git a/doc/command/scion-pki/scion-pki_certificate_verify_ca.rst b/doc/command/scion-pki/scion-pki_certificate_verify_ca.rst old mode 100644 new mode 100755 index 7811e8026..ae53d7d74 --- a/doc/command/scion-pki/scion-pki_certificate_verify_ca.rst +++ b/doc/command/scion-pki/scion-pki_certificate_verify_ca.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_certificate_verify_ca: scion-pki certificate verify ca @@ -37,5 +39,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki certificate verify `_ - Verify a certificate chain +* :ref:`scion-pki certificate verify ` - Verify a certificate chain diff --git a/doc/command/scion-pki/scion-pki_completion.rst b/doc/command/scion-pki/scion-pki_completion.rst old mode 100644 new mode 100755 index ad380b005..96b229fbf --- a/doc/command/scion-pki/scion-pki_completion.rst +++ b/doc/command/scion-pki/scion-pki_completion.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_completion: scion-pki completion @@ -23,9 +25,9 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki `_ - SCION Control Plane PKI Management Tool -* `scion-pki completion bash `_ - Generate the autocompletion script for bash -* `scion-pki completion fish `_ - Generate the autocompletion script for fish -* `scion-pki completion powershell `_ - Generate the autocompletion script for powershell -* `scion-pki completion zsh `_ - Generate the autocompletion script for zsh +* :ref:`scion-pki ` - SCION Control Plane PKI Management Tool +* :ref:`scion-pki completion bash ` - Generate the autocompletion script for bash +* :ref:`scion-pki completion fish ` - Generate the autocompletion script for fish +* :ref:`scion-pki completion powershell ` - Generate the autocompletion script for powershell +* :ref:`scion-pki completion zsh ` - Generate the autocompletion script for zsh diff --git a/doc/command/scion-pki/scion-pki_completion_bash.rst b/doc/command/scion-pki/scion-pki_completion_bash.rst old mode 100644 new mode 100755 index fbae4ea3b..b8eb1654c --- a/doc/command/scion-pki/scion-pki_completion_bash.rst +++ b/doc/command/scion-pki/scion-pki_completion_bash.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_completion_bash: scion-pki completion bash @@ -46,5 +48,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki completion `_ - Generate the autocompletion script for the specified shell +* :ref:`scion-pki completion ` - Generate the autocompletion script for the specified shell diff --git a/doc/command/scion-pki/scion-pki_completion_fish.rst b/doc/command/scion-pki/scion-pki_completion_fish.rst old mode 100644 new mode 100755 index 918f5b376..22321205a --- a/doc/command/scion-pki/scion-pki_completion_fish.rst +++ b/doc/command/scion-pki/scion-pki_completion_fish.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_completion_fish: scion-pki completion fish @@ -37,5 +39,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki completion `_ - Generate the autocompletion script for the specified shell +* :ref:`scion-pki completion ` - Generate the autocompletion script for the specified shell diff --git a/doc/command/scion-pki/scion-pki_completion_powershell.rst b/doc/command/scion-pki/scion-pki_completion_powershell.rst old mode 100644 new mode 100755 index 27d0b9793..c8c3d4c6c --- a/doc/command/scion-pki/scion-pki_completion_powershell.rst +++ b/doc/command/scion-pki/scion-pki_completion_powershell.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_completion_powershell: scion-pki completion powershell @@ -34,5 +36,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki completion `_ - Generate the autocompletion script for the specified shell +* :ref:`scion-pki completion ` - Generate the autocompletion script for the specified shell diff --git a/doc/command/scion-pki/scion-pki_completion_zsh.rst b/doc/command/scion-pki/scion-pki_completion_zsh.rst old mode 100644 new mode 100755 index 92e3178fd..be8c994f8 --- a/doc/command/scion-pki/scion-pki_completion_zsh.rst +++ b/doc/command/scion-pki/scion-pki_completion_zsh.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_completion_zsh: scion-pki completion zsh @@ -44,5 +46,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki completion `_ - Generate the autocompletion script for the specified shell +* :ref:`scion-pki completion ` - Generate the autocompletion script for the specified shell diff --git a/doc/command/scion-pki/scion-pki_key.rst b/doc/command/scion-pki/scion-pki_key.rst old mode 100644 new mode 100755 index 39eb5ab91..6d62fe7a6 --- a/doc/command/scion-pki/scion-pki_key.rst +++ b/doc/command/scion-pki/scion-pki_key.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_key: scion-pki key @@ -21,10 +23,10 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki `_ - SCION Control Plane PKI Management Tool -* `scion-pki key fingerprint `_ - Computes the fingerprint of the provided key -* `scion-pki key match `_ - Match the key with other trust objects -* `scion-pki key private `_ - Generate private key at the specified location -* `scion-pki key public `_ - Generate public key for the provided private key -* `scion-pki key symmetric `_ - Generate symmetric key at the specified location +* :ref:`scion-pki ` - SCION Control Plane PKI Management Tool +* :ref:`scion-pki key fingerprint ` - Computes the fingerprint of the provided key +* :ref:`scion-pki key match ` - Match the key with other trust objects +* :ref:`scion-pki key private ` - Generate private key at the specified location +* :ref:`scion-pki key public ` - Generate public key for the provided private key +* :ref:`scion-pki key symmetric ` - Generate symmetric key at the specified location diff --git a/doc/command/scion-pki/scion-pki_key_fingerprint.rst b/doc/command/scion-pki/scion-pki_key_fingerprint.rst old mode 100644 new mode 100755 index 221403de7..93082b29c --- a/doc/command/scion-pki/scion-pki_key_fingerprint.rst +++ b/doc/command/scion-pki/scion-pki_key_fingerprint.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_key_fingerprint: scion-pki key fingerprint @@ -46,5 +48,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki key `_ - Manage private and public keys +* :ref:`scion-pki key ` - Manage private and public keys diff --git a/doc/command/scion-pki/scion-pki_key_match.rst b/doc/command/scion-pki/scion-pki_key_match.rst old mode 100644 new mode 100755 index a29d1901f..880951084 --- a/doc/command/scion-pki/scion-pki_key_match.rst +++ b/doc/command/scion-pki/scion-pki_key_match.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_key_match: scion-pki key match @@ -21,6 +23,6 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki key `_ - Manage private and public keys -* `scion-pki key match certificate `_ - Find the matching certificate for the key +* :ref:`scion-pki key ` - Manage private and public keys +* :ref:`scion-pki key match certificate ` - Find the matching certificate for the key diff --git a/doc/command/scion-pki/scion-pki_key_match_certificate.rst b/doc/command/scion-pki/scion-pki_key_match_certificate.rst old mode 100644 new mode 100755 index 6ee78e334..2cc013f11 --- a/doc/command/scion-pki/scion-pki_key_match_certificate.rst +++ b/doc/command/scion-pki/scion-pki_key_match_certificate.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_key_match_certificate: scion-pki key match certificate @@ -39,5 +41,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki key match `_ - Match the key with other trust objects +* :ref:`scion-pki key match ` - Match the key with other trust objects diff --git a/doc/command/scion-pki/scion-pki_key_private.rst b/doc/command/scion-pki/scion-pki_key_private.rst old mode 100644 new mode 100755 index 93a4aa5f0..ceb294936 --- a/doc/command/scion-pki/scion-pki_key_private.rst +++ b/doc/command/scion-pki/scion-pki_key_private.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_key_private: scion-pki key private @@ -38,5 +40,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki key `_ - Manage private and public keys +* :ref:`scion-pki key ` - Manage private and public keys diff --git a/doc/command/scion-pki/scion-pki_key_public.rst b/doc/command/scion-pki/scion-pki_key_public.rst old mode 100644 new mode 100755 index 51c09d8ec..2c5c160f4 --- a/doc/command/scion-pki/scion-pki_key_public.rst +++ b/doc/command/scion-pki/scion-pki_key_public.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_key_public: scion-pki key public @@ -38,5 +40,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki key `_ - Manage private and public keys +* :ref:`scion-pki key ` - Manage private and public keys diff --git a/doc/command/scion-pki/scion-pki_key_symmetric.rst b/doc/command/scion-pki/scion-pki_key_symmetric.rst old mode 100644 new mode 100755 index 77fe7ceb7..e340a5f34 --- a/doc/command/scion-pki/scion-pki_key_symmetric.rst +++ b/doc/command/scion-pki/scion-pki_key_symmetric.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_key_symmetric: scion-pki key symmetric @@ -39,5 +41,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki key `_ - Manage private and public keys +* :ref:`scion-pki key ` - Manage private and public keys diff --git a/doc/command/scion-pki/scion-pki_trc.rst b/doc/command/scion-pki/scion-pki_trc.rst old mode 100644 new mode 100755 index ef711281b..1fe83166b --- a/doc/command/scion-pki/scion-pki_trc.rst +++ b/doc/command/scion-pki/scion-pki_trc.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_trc: scion-pki trc @@ -21,12 +23,12 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki `_ - SCION Control Plane PKI Management Tool -* `scion-pki trc combine `_ - Combine partially signed TRCs -* `scion-pki trc extract `_ - Extract parts of a signed TRC -* `scion-pki trc format `_ - Reformat a TRC or TRC payload -* `scion-pki trc inspect `_ - Represent TRC in a human readable form -* `scion-pki trc payload `_ - Generate new TRC payload -* `scion-pki trc sign `_ - Sign a TRC -* `scion-pki trc verify `_ - Verify a TRC chain +* :ref:`scion-pki ` - SCION Control Plane PKI Management Tool +* :ref:`scion-pki trc combine ` - Combine partially signed TRCs +* :ref:`scion-pki trc extract ` - Extract parts of a signed TRC +* :ref:`scion-pki trc format ` - Reformat a TRC or TRC payload +* :ref:`scion-pki trc inspect ` - Represent TRC in a human readable form +* :ref:`scion-pki trc payload ` - Generate new TRC payload +* :ref:`scion-pki trc sign ` - Sign a TRC +* :ref:`scion-pki trc verify ` - Verify a TRC chain diff --git a/doc/command/scion-pki/scion-pki_trc_combine.rst b/doc/command/scion-pki/scion-pki_trc_combine.rst old mode 100644 new mode 100755 index 042471fb8..e6be01c22 --- a/doc/command/scion-pki/scion-pki_trc_combine.rst +++ b/doc/command/scion-pki/scion-pki_trc_combine.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_trc_combine: scion-pki trc combine @@ -40,5 +42,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki trc `_ - Manage TRCs for the SCION control plane PKI +* :ref:`scion-pki trc ` - Manage TRCs for the SCION control plane PKI diff --git a/doc/command/scion-pki/scion-pki_trc_extract.rst b/doc/command/scion-pki/scion-pki_trc_extract.rst old mode 100644 new mode 100755 index 2ddfd4e30..3e4f61c52 --- a/doc/command/scion-pki/scion-pki_trc_extract.rst +++ b/doc/command/scion-pki/scion-pki_trc_extract.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_trc_extract: scion-pki trc extract @@ -21,7 +23,7 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki trc `_ - Manage TRCs for the SCION control plane PKI -* `scion-pki trc extract certificates `_ - Extract the bundled certificates -* `scion-pki trc extract payload `_ - Extract the TRC payload +* :ref:`scion-pki trc ` - Manage TRCs for the SCION control plane PKI +* :ref:`scion-pki trc extract certificates ` - Extract the bundled certificates +* :ref:`scion-pki trc extract payload ` - Extract the TRC payload diff --git a/doc/command/scion-pki/scion-pki_trc_extract_certificates.rst b/doc/command/scion-pki/scion-pki_trc_extract_certificates.rst old mode 100644 new mode 100755 index 092703d6f..2fc03b11e --- a/doc/command/scion-pki/scion-pki_trc_extract_certificates.rst +++ b/doc/command/scion-pki/scion-pki_trc_extract_certificates.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_trc_extract_certificates: scion-pki trc extract certificates @@ -33,5 +35,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki trc extract `_ - Extract parts of a signed TRC +* :ref:`scion-pki trc extract ` - Extract parts of a signed TRC diff --git a/doc/command/scion-pki/scion-pki_trc_extract_payload.rst b/doc/command/scion-pki/scion-pki_trc_extract_payload.rst old mode 100644 new mode 100755 index a0d961ad8..994de7f42 --- a/doc/command/scion-pki/scion-pki_trc_extract_payload.rst +++ b/doc/command/scion-pki/scion-pki_trc_extract_payload.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_trc_extract_payload: scion-pki trc extract payload @@ -41,5 +43,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki trc extract `_ - Extract parts of a signed TRC +* :ref:`scion-pki trc extract ` - Extract parts of a signed TRC diff --git a/doc/command/scion-pki/scion-pki_trc_format.rst b/doc/command/scion-pki/scion-pki_trc_format.rst old mode 100644 new mode 100755 index c427433f1..7ae5f12ea --- a/doc/command/scion-pki/scion-pki_trc_format.rst +++ b/doc/command/scion-pki/scion-pki_trc_format.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_trc_format: scion-pki trc format @@ -43,5 +45,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki trc `_ - Manage TRCs for the SCION control plane PKI +* :ref:`scion-pki trc ` - Manage TRCs for the SCION control plane PKI diff --git a/doc/command/scion-pki/scion-pki_trc_inspect.rst b/doc/command/scion-pki/scion-pki_trc_inspect.rst old mode 100644 new mode 100755 index 682268c93..39ffbd38d --- a/doc/command/scion-pki/scion-pki_trc_inspect.rst +++ b/doc/command/scion-pki/scion-pki_trc_inspect.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_trc_inspect: scion-pki trc inspect @@ -43,5 +45,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki trc `_ - Manage TRCs for the SCION control plane PKI +* :ref:`scion-pki trc ` - Manage TRCs for the SCION control plane PKI diff --git a/doc/command/scion-pki/scion-pki_trc_payload.rst b/doc/command/scion-pki/scion-pki_trc_payload.rst old mode 100644 new mode 100755 index 99c2edbe6..41dc186b4 --- a/doc/command/scion-pki/scion-pki_trc_payload.rst +++ b/doc/command/scion-pki/scion-pki_trc_payload.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_trc_payload: scion-pki trc payload @@ -47,5 +49,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki trc `_ - Manage TRCs for the SCION control plane PKI +* :ref:`scion-pki trc ` - Manage TRCs for the SCION control plane PKI diff --git a/doc/command/scion-pki/scion-pki_trc_sign.rst b/doc/command/scion-pki/scion-pki_trc_sign.rst old mode 100644 new mode 100755 index 53f84bc12..e1b8e9b12 --- a/doc/command/scion-pki/scion-pki_trc_sign.rst +++ b/doc/command/scion-pki/scion-pki_trc_sign.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_trc_sign: scion-pki trc sign @@ -47,5 +49,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki trc `_ - Manage TRCs for the SCION control plane PKI +* :ref:`scion-pki trc ` - Manage TRCs for the SCION control plane PKI diff --git a/doc/command/scion-pki/scion-pki_trc_verify.rst b/doc/command/scion-pki/scion-pki_trc_verify.rst old mode 100644 new mode 100755 index cee05518b..82ca8c6e0 --- a/doc/command/scion-pki/scion-pki_trc_verify.rst +++ b/doc/command/scion-pki/scion-pki_trc_verify.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_trc_verify: scion-pki trc verify @@ -43,5 +45,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki trc `_ - Manage TRCs for the SCION control plane PKI +* :ref:`scion-pki trc ` - Manage TRCs for the SCION control plane PKI diff --git a/doc/command/scion-pki/scion-pki_version.rst b/doc/command/scion-pki/scion-pki_version.rst old mode 100644 new mode 100755 index 68c755542..ebd37f4f4 --- a/doc/command/scion-pki/scion-pki_version.rst +++ b/doc/command/scion-pki/scion-pki_version.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion-pki_version: scion-pki version @@ -25,5 +27,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion-pki `_ - SCION Control Plane PKI Management Tool +* :ref:`scion-pki ` - SCION Control Plane PKI Management Tool diff --git a/doc/command/scion/scion.rst b/doc/command/scion/scion.rst old mode 100644 new mode 100755 index f8ce8968b..02fe7d764 --- a/doc/command/scion/scion.rst +++ b/doc/command/scion/scion.rst @@ -1,15 +1,17 @@ +:orphan: + .. _scion: scion ----- -A clean-slate Internet architecture +SCION networking utilities. Synopsis ~~~~~~~~ -A clean-slate Internet architecture +scion is a collection of command line utilities for hosts in the SCION Internet. Options ~~~~~~~ @@ -21,10 +23,10 @@ Options SEE ALSO ~~~~~~~~ -* `scion address `_ - Show (one of) this host's SCION address(es) -* `scion completion `_ - Generate the autocompletion script for the specified shell -* `scion ping `_ - Test connectivity to a remote SCION host using SCMP echo packets -* `scion showpaths `_ - Display paths to a SCION AS -* `scion traceroute `_ - Trace the SCION route to a remote SCION AS using SCMP traceroute packets -* `scion version `_ - Show the SCION version information +* :ref:`scion address ` - Show (one of) this host's SCION address(es) +* :ref:`scion completion ` - Generate the autocompletion script for the specified shell +* :ref:`scion ping ` - Test connectivity to a remote SCION host using SCMP echo packets +* :ref:`scion showpaths ` - Display paths to a SCION AS +* :ref:`scion traceroute ` - Trace the SCION route to a remote SCION AS using SCMP traceroute packets +* :ref:`scion version ` - Show the SCION version information diff --git a/doc/command/scion/scion_address.rst b/doc/command/scion/scion_address.rst old mode 100644 new mode 100755 index 13f93b316..d5afd61ed --- a/doc/command/scion/scion_address.rst +++ b/doc/command/scion/scion_address.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion_address: scion address @@ -43,5 +45,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion `_ - A clean-slate Internet architecture +* :ref:`scion ` - SCION networking utilities. diff --git a/doc/command/scion/scion_completion.rst b/doc/command/scion/scion_completion.rst old mode 100644 new mode 100755 index 469046e99..22af68d85 --- a/doc/command/scion/scion_completion.rst +++ b/doc/command/scion/scion_completion.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion_completion: scion completion @@ -23,9 +25,9 @@ Options SEE ALSO ~~~~~~~~ -* `scion `_ - A clean-slate Internet architecture -* `scion completion bash `_ - Generate the autocompletion script for bash -* `scion completion fish `_ - Generate the autocompletion script for fish -* `scion completion powershell `_ - Generate the autocompletion script for powershell -* `scion completion zsh `_ - Generate the autocompletion script for zsh +* :ref:`scion ` - SCION networking utilities. +* :ref:`scion completion bash ` - Generate the autocompletion script for bash +* :ref:`scion completion fish ` - Generate the autocompletion script for fish +* :ref:`scion completion powershell ` - Generate the autocompletion script for powershell +* :ref:`scion completion zsh ` - Generate the autocompletion script for zsh diff --git a/doc/command/scion/scion_completion_bash.rst b/doc/command/scion/scion_completion_bash.rst old mode 100644 new mode 100755 index 52fa31448..beb0bf0ad --- a/doc/command/scion/scion_completion_bash.rst +++ b/doc/command/scion/scion_completion_bash.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion_completion_bash: scion completion bash @@ -46,5 +48,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion completion `_ - Generate the autocompletion script for the specified shell +* :ref:`scion completion ` - Generate the autocompletion script for the specified shell diff --git a/doc/command/scion/scion_completion_fish.rst b/doc/command/scion/scion_completion_fish.rst old mode 100644 new mode 100755 index 787e09ebb..4153c8a3b --- a/doc/command/scion/scion_completion_fish.rst +++ b/doc/command/scion/scion_completion_fish.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion_completion_fish: scion completion fish @@ -37,5 +39,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion completion `_ - Generate the autocompletion script for the specified shell +* :ref:`scion completion ` - Generate the autocompletion script for the specified shell diff --git a/doc/command/scion/scion_completion_powershell.rst b/doc/command/scion/scion_completion_powershell.rst old mode 100644 new mode 100755 index e05a0c429..db993b541 --- a/doc/command/scion/scion_completion_powershell.rst +++ b/doc/command/scion/scion_completion_powershell.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion_completion_powershell: scion completion powershell @@ -34,5 +36,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion completion `_ - Generate the autocompletion script for the specified shell +* :ref:`scion completion ` - Generate the autocompletion script for the specified shell diff --git a/doc/command/scion/scion_completion_zsh.rst b/doc/command/scion/scion_completion_zsh.rst old mode 100644 new mode 100755 index 8647d261f..8d176feed --- a/doc/command/scion/scion_completion_zsh.rst +++ b/doc/command/scion/scion_completion_zsh.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion_completion_zsh: scion completion zsh @@ -44,5 +46,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion completion `_ - Generate the autocompletion script for the specified shell +* :ref:`scion completion ` - Generate the autocompletion script for the specified shell diff --git a/doc/command/scion/scion_ping.rst b/doc/command/scion/scion_ping.rst old mode 100644 new mode 100755 index f79691cf0..f39f0bbf9 --- a/doc/command/scion/scion_ping.rst +++ b/doc/command/scion/scion_ping.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion_ping: scion ping @@ -114,5 +116,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion `_ - A clean-slate Internet architecture +* :ref:`scion ` - SCION networking utilities. diff --git a/doc/command/scion/scion_showpaths.rst b/doc/command/scion/scion_showpaths.rst old mode 100644 new mode 100755 index 9801251fe..fd7b5c32c --- a/doc/command/scion/scion_showpaths.rst +++ b/doc/command/scion/scion_showpaths.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion_showpaths: scion showpaths @@ -108,5 +110,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion `_ - A clean-slate Internet architecture +* :ref:`scion ` - SCION networking utilities. diff --git a/doc/command/scion/scion_traceroute.rst b/doc/command/scion/scion_traceroute.rst old mode 100644 new mode 100755 index 67ea2fb5d..f36e8e764 --- a/doc/command/scion/scion_traceroute.rst +++ b/doc/command/scion/scion_traceroute.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion_traceroute: scion traceroute @@ -95,5 +97,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion `_ - A clean-slate Internet architecture +* :ref:`scion ` - SCION networking utilities. diff --git a/doc/command/scion/scion_version.rst b/doc/command/scion/scion_version.rst old mode 100644 new mode 100755 index 390d6beb6..3a1ad69e2 --- a/doc/command/scion/scion_version.rst +++ b/doc/command/scion/scion_version.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scion_version: scion version @@ -32,5 +34,5 @@ Options SEE ALSO ~~~~~~~~ -* `scion `_ - A clean-slate Internet architecture +* :ref:`scion ` - SCION networking utilities. diff --git a/doc/conf.py b/doc/conf.py index 3834fa023..702fc43d7 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -19,8 +19,8 @@ # -- Project information ----------------------------------------------------- project = 'SCION' -copyright = '2021, Anapaya Systems, ETH Zurich' -author = 'Anapaya Systems, ETH Zurich' +copyright = '2023, Anapaya Systems, ETH Zurich, SCION Association' +author = 'Anapaya Systems, ETH Zurich, SCION Association' # -- General configuration --------------------------------------------------- @@ -39,7 +39,11 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = [ + 'venv', 'requirements.in', 'requirements.txt', + '_build', 'Thumbs.db', '.DS_Store', + 'manuals/*/*', # manuals/.rst uses "include" directive to compose files from subdirectories +] master_doc = 'index' diff --git a/doc/cryptography/certificates.rst b/doc/cryptography/certificates.rst index 0a18c43dc..76e7973ed 100644 --- a/doc/cryptography/certificates.rst +++ b/doc/cryptography/certificates.rst @@ -566,10 +566,3 @@ must be set. If used on the server-side of CP TLS session establishment, establishment, ``id-kp-clientAuth`` must be set. **Basic constraints**. The extension should not be included. - -Resources -========= - -Most of the references linked from this document can be found in the `Anapaya -standards repository -`_. diff --git a/doc/index.rst b/doc/index.rst index 638f45566..a5e77cf52 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -36,7 +36,7 @@ is a good place to start. endhost-bootstrap .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :caption: Operational manuals: manuals/common @@ -47,15 +47,8 @@ is a good place to start. manuals/gateway .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :caption: CLI tools: command/scion/scion command/scion-pki/scion-pki - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/doc/requirements.in b/doc/requirements.in new file mode 100644 index 000000000..1a9af83dd --- /dev/null +++ b/doc/requirements.in @@ -0,0 +1,4 @@ +Sphinx +recommonmark +sphinx-autobuild +sphinx-rtd-theme diff --git a/doc/requirements.txt b/doc/requirements.txt index b2e599888..adac82314 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,2 +1,292 @@ -docutils<0.18 -sphinx-copybutton==0.4.0 +# +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: +# +# pip-compile --generate-hashes --resolver=backtracking requirements.in +# +alabaster==0.7.13 \ + --hash=sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3 \ + --hash=sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2 + # via sphinx +babel==2.11.0 \ + --hash=sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe \ + --hash=sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6 + # via sphinx +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 + # via requests +charset-normalizer==3.0.1 \ + --hash=sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b \ + --hash=sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42 \ + --hash=sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d \ + --hash=sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b \ + --hash=sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a \ + --hash=sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59 \ + --hash=sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154 \ + --hash=sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1 \ + --hash=sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c \ + --hash=sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a \ + --hash=sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d \ + --hash=sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6 \ + --hash=sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b \ + --hash=sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b \ + --hash=sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783 \ + --hash=sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5 \ + --hash=sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918 \ + --hash=sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555 \ + --hash=sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639 \ + --hash=sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786 \ + --hash=sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e \ + --hash=sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed \ + --hash=sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820 \ + --hash=sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8 \ + --hash=sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3 \ + --hash=sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541 \ + --hash=sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14 \ + --hash=sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be \ + --hash=sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e \ + --hash=sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76 \ + --hash=sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b \ + --hash=sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c \ + --hash=sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b \ + --hash=sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3 \ + --hash=sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc \ + --hash=sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6 \ + --hash=sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59 \ + --hash=sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4 \ + --hash=sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d \ + --hash=sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d \ + --hash=sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3 \ + --hash=sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a \ + --hash=sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea \ + --hash=sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6 \ + --hash=sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e \ + --hash=sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603 \ + --hash=sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24 \ + --hash=sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a \ + --hash=sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58 \ + --hash=sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678 \ + --hash=sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a \ + --hash=sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c \ + --hash=sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6 \ + --hash=sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18 \ + --hash=sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174 \ + --hash=sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317 \ + --hash=sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f \ + --hash=sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc \ + --hash=sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837 \ + --hash=sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41 \ + --hash=sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c \ + --hash=sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579 \ + --hash=sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753 \ + --hash=sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8 \ + --hash=sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291 \ + --hash=sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087 \ + --hash=sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866 \ + --hash=sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3 \ + --hash=sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d \ + --hash=sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1 \ + --hash=sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca \ + --hash=sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e \ + --hash=sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db \ + --hash=sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72 \ + --hash=sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d \ + --hash=sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc \ + --hash=sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539 \ + --hash=sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d \ + --hash=sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af \ + --hash=sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b \ + --hash=sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602 \ + --hash=sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f \ + --hash=sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478 \ + --hash=sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c \ + --hash=sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e \ + --hash=sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479 \ + --hash=sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7 \ + --hash=sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8 + # via requests +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via sphinx-autobuild +commonmark==0.9.1 \ + --hash=sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60 \ + --hash=sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9 + # via recommonmark +docutils==0.18.1 \ + --hash=sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c \ + --hash=sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06 + # via + # recommonmark + # sphinx + # sphinx-rtd-theme +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 + # via requests +imagesize==1.4.1 \ + --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ + --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a + # via sphinx +importlib-metadata==6.0.0 \ + --hash=sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad \ + --hash=sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d + # via sphinx +jinja2==3.1.2 \ + --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ + --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 + # via sphinx +livereload==2.6.3 \ + --hash=sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869 \ + --hash=sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4 + # via sphinx-autobuild +markupsafe==2.1.2 \ + --hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \ + --hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \ + --hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 \ + --hash=sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460 \ + --hash=sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7 \ + --hash=sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0 \ + --hash=sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1 \ + --hash=sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa \ + --hash=sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03 \ + --hash=sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323 \ + --hash=sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65 \ + --hash=sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013 \ + --hash=sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036 \ + --hash=sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f \ + --hash=sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4 \ + --hash=sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419 \ + --hash=sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2 \ + --hash=sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619 \ + --hash=sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a \ + --hash=sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a \ + --hash=sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd \ + --hash=sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7 \ + --hash=sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666 \ + --hash=sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65 \ + --hash=sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859 \ + --hash=sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625 \ + --hash=sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff \ + --hash=sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156 \ + --hash=sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd \ + --hash=sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba \ + --hash=sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f \ + --hash=sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1 \ + --hash=sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094 \ + --hash=sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a \ + --hash=sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513 \ + --hash=sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed \ + --hash=sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d \ + --hash=sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3 \ + --hash=sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147 \ + --hash=sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c \ + --hash=sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603 \ + --hash=sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601 \ + --hash=sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a \ + --hash=sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1 \ + --hash=sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d \ + --hash=sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3 \ + --hash=sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54 \ + --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ + --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ + --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 + # via jinja2 +packaging==23.0 \ + --hash=sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2 \ + --hash=sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97 + # via sphinx +pygments==2.14.0 \ + --hash=sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297 \ + --hash=sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717 + # via sphinx +pytz==2022.7.1 \ + --hash=sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0 \ + --hash=sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a + # via babel +recommonmark==0.7.1 \ + --hash=sha256:1b1db69af0231efce3fa21b94ff627ea33dee7079a01dd0a7f8482c3da148b3f \ + --hash=sha256:bdb4db649f2222dcd8d2d844f0006b958d627f732415d399791ee436a3686d67 + # via -r requirements.in +requests==2.28.2 \ + --hash=sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa \ + --hash=sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf + # via sphinx +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via livereload +snowballstemmer==2.2.0 \ + --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \ + --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a + # via sphinx +sphinx==6.1.3 \ + --hash=sha256:0dac3b698538ffef41716cf97ba26c1c7788dba73ce6f150c1ff5b4720786dd2 \ + --hash=sha256:807d1cb3d6be87eb78a381c3e70ebd8d346b9a25f3753e9947e866b2786865fc + # via + # -r requirements.in + # recommonmark + # sphinx-autobuild + # sphinx-rtd-theme +sphinx-autobuild==2021.3.14 \ + --hash=sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac \ + --hash=sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05 + # via -r requirements.in +sphinx-rtd-theme==1.2.0 \ + --hash=sha256:a0d8bd1a2ed52e0b338cbe19c4b2eef3c5e7a048769753dac6a9f059c7b641b8 \ + --hash=sha256:f823f7e71890abe0ac6aaa6013361ea2696fc8d3e1fa798f463e82bdb77eeff2 + # via -r requirements.in +sphinxcontrib-applehelp==1.0.4 \ + --hash=sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228 \ + --hash=sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e + # via sphinx +sphinxcontrib-devhelp==1.0.2 \ + --hash=sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e \ + --hash=sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4 + # via sphinx +sphinxcontrib-htmlhelp==2.0.1 \ + --hash=sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff \ + --hash=sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903 + # via sphinx +sphinxcontrib-jquery==2.0.0 \ + --hash=sha256:8fb65f6dba84bf7bcd1aea1f02ab3955ac34611d838bcc95d4983b805b234daa \ + --hash=sha256:ed47fa425c338ffebe3c37e1cdb56e30eb806116b85f01055b158c7057fdb995 + # via sphinx-rtd-theme +sphinxcontrib-jsmath==1.0.1 \ + --hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \ + --hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8 + # via sphinx +sphinxcontrib-qthelp==1.0.3 \ + --hash=sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72 \ + --hash=sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6 + # via sphinx +sphinxcontrib-serializinghtml==1.1.5 \ + --hash=sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd \ + --hash=sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952 + # via sphinx +tornado==6.2 \ + --hash=sha256:1d54d13ab8414ed44de07efecb97d4ef7c39f7438cf5e976ccd356bebb1b5fca \ + --hash=sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72 \ + --hash=sha256:5c87076709343557ef8032934ce5f637dbb552efa7b21d08e89ae7619ed0eb23 \ + --hash=sha256:5f8c52d219d4995388119af7ccaa0bcec289535747620116a58d830e7c25d8a8 \ + --hash=sha256:6fdfabffd8dfcb6cf887428849d30cf19a3ea34c2c248461e1f7d718ad30b66b \ + --hash=sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9 \ + --hash=sha256:9b630419bde84ec666bfd7ea0a4cb2a8a651c2d5cccdbdd1972a0c859dfc3c13 \ + --hash=sha256:b8150f721c101abdef99073bf66d3903e292d851bee51910839831caba341a75 \ + --hash=sha256:ba09ef14ca9893954244fd872798b4ccb2367c165946ce2dd7376aebdde8e3ac \ + --hash=sha256:d3a2f5999215a3a06a4fc218026cd84c61b8b2b40ac5296a6db1f1451ef04c1e \ + --hash=sha256:e5f923aa6a47e133d1cf87d60700889d7eae68988704e20c75fb2d65677a8e4b + # via livereload +urllib3==1.26.14 \ + --hash=sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72 \ + --hash=sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1 + # via requests +zipp==3.14.0 \ + --hash=sha256:188834565033387710d046e3fe96acfc9b5e86cbca7f39ff69cf21a4128198b7 \ + --hash=sha256:9e5421e176ef5ab4c0ad896624e87a7b2f07aca746c9b2aa305952800cb8eecb + # via importlib-metadata + +# WARNING: The following packages were not pinned, but pip requires them to be +# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag. +# setuptools diff --git a/doc/testing/mocks.rst b/doc/testing/mocks.rst index 0d22da32d..2250cdab4 100644 --- a/doc/testing/mocks.rst +++ b/doc/testing/mocks.rst @@ -29,7 +29,7 @@ interfaces. This would look like the following:: ) For an example, refer to -`this exmaple file `_. +`this exmaple file `_. For further information on the gomock bazel rules, refer to `gomock for Bazel `_. diff --git a/scion-pki/certs/inspect.go b/scion-pki/certs/inspect.go index 437a1c9b9..bbc222f5e 100644 --- a/scion-pki/certs/inspect.go +++ b/scion-pki/certs/inspect.go @@ -35,7 +35,7 @@ func newInspectCmd(pather command.Pather) *cobra.Command { cmd := &cobra.Command{ Use: "inspect [flags] ", - Short: "Inspect a certificate or a certificate signing request ", + Short: "Inspect a certificate or a certificate signing request", Long: `outputs the certificate chain or a certificat signing request (CSR) in human readable format.`, Example: fmt.Sprintf( diff --git a/scion-pki/cmd/scion-pki/gendocs.go b/scion-pki/cmd/scion-pki/gendocs.go index 961abe4bd..371e27fd4 100644 --- a/scion-pki/cmd/scion-pki/gendocs.go +++ b/scion-pki/cmd/scion-pki/gendocs.go @@ -39,11 +39,11 @@ in the location given as an argument.`, directory := args[0] filePrepender := func(filename string) string { - return "" + return ":orphan:\n\n" } linkHandler := func(name, ref string) string { - return fmt.Sprintf("`%s <%s.html>`_", name, ref) + return fmt.Sprintf(":ref:`%s <%s>`", name, ref) } if err := os.MkdirAll(directory, 0755); err != nil { return serrors.WrapStr("creating directory", err, "directory", directory) diff --git a/scion-pki/cmd/scion-pki/main.go b/scion-pki/cmd/scion-pki/main.go index 1e783e10a..c64f4afd7 100644 --- a/scion-pki/cmd/scion-pki/main.go +++ b/scion-pki/cmd/scion-pki/main.go @@ -70,6 +70,7 @@ func main() { cmd.SetHelpTemplate(`{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces | removeEscape}} {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`) + cmd.DisableAutoGenTag = true if err := cmd.Execute(); err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) diff --git a/scion/cmd/scion/gendocs.go b/scion/cmd/scion/gendocs.go index 1e87db44b..924938087 100644 --- a/scion/cmd/scion/gendocs.go +++ b/scion/cmd/scion/gendocs.go @@ -39,11 +39,11 @@ in the location given as an argument.`, directory := args[0] filePrepender := func(filename string) string { - return "" + return ":orphan:\n\n" // } linkHandler := func(name, ref string) string { - return fmt.Sprintf("`%s <%s.html>`_", name, ref) + return fmt.Sprintf(":ref:`%s <%s>`", name, ref) } if err := os.MkdirAll(directory, 0755); err != nil { return serrors.WrapStr("creating directory", err, "directory", directory) diff --git a/scion/cmd/scion/main.go b/scion/cmd/scion/main.go index c99b61b2b..8c3018891 100644 --- a/scion/cmd/scion/main.go +++ b/scion/cmd/scion/main.go @@ -36,8 +36,10 @@ func main() { executable := filepath.Base(os.Args[0]) cmd := &cobra.Command{ Use: executable, - Short: "A clean-slate Internet architecture", - Args: cobra.NoArgs, + Short: "SCION networking utilities.", + Long: executable + + " is a collection of command line utilities for hosts in the SCION Internet.", + Args: cobra.NoArgs, // Silence the errors, since we print them in main. Otherwise, cobra // will print any non-nil errors returned by a RunE function. // See https://github.com/spf13/cobra/issues/340. @@ -71,6 +73,7 @@ func main() { cmd.SetHelpTemplate(`{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces | removeEscape}} {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`) + cmd.DisableAutoGenTag = true if err := cmd.Execute(); err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) From 914cdd6747e7088ef7447c87be9ec8b05e7550e7 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Wed, 22 Feb 2023 21:06:52 +0100 Subject: [PATCH 013/255] doc: fix python version in readthedocs config (#4321) In #4319, the python requirements file was generated for python3.8 but our build configuration file still referred to 3.7, resulting in broken builds. Also bump the ubuntu version to latest LTS, because, why not. Also move the .readthedocs.yaml file to the project root, where this should be located according to the documentation. The readthedocs build log (confusingly) mentioned that this file was not present. Either this was a spurious error message or the file was indeed ignored and it just happened to match the defaults. --- .readthedocs.yaml | 17 +++++++++++++++++ doc/.readthedocs.yaml | 13 ------------- 2 files changed, 17 insertions(+), 13 deletions(-) create mode 100644 .readthedocs.yaml delete mode 100644 doc/.readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..973c7d33b --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,17 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.8" + +sphinx: + configuration: doc/conf.py + +python: + install: + - requirements: doc/requirements.txt diff --git a/doc/.readthedocs.yaml b/doc/.readthedocs.yaml deleted file mode 100644 index 4cdece771..000000000 --- a/doc/.readthedocs.yaml +++ /dev/null @@ -1,13 +0,0 @@ -version: 2 - -build: - os: ubuntu-18.04 - tools: - python: "3.7" - -sphinx: - configuration: doc/conf.py - -python: - install: - - requirements: doc/requirements.txt From 1fd088bddf3a22fb23ae6a66f7bcf3f523dc9d6f Mon Sep 17 00:00:00 2001 From: Lukas Vogel Date: Fri, 24 Feb 2023 11:33:55 +0100 Subject: [PATCH 014/255] deps: update a lot of dependencies (#4323) This commit updates almost all of the direct dependencies to the latest version. --- .buildkite/pipeline.yml | 2 +- Makefile | 8 +- WORKSPACE | 12 +- control/mgmtapi/api.go | 188 +- control/mgmtapi/api_test.go | 48 +- control/mgmtapi/client.gen.go | 97 +- control/mgmtapi/server.gen.go | 202 +- control/mgmtapi/testdata/TestAPI_beacon | 2 +- .../mgmtapi/testdata/TestAPI_beacon_id_prefix | 2 +- control/mgmtapi/testdata/TestAPI_beacons | 4 +- .../testdata/TestAPI_beacons_descending_order | 4 +- .../testdata/TestAPI_beacons_existing_usages | 2 +- .../TestAPI_beacons_sort_by_ingress_interface | 4 +- .../TestAPI_health_signer_degraded_trc_fails | 2 +- .../testdata/TestAPI_health_signer_error | 4 +- .../testdata/TestAPI_health_signer_fails | 2 +- .../TestAPI_health_signer_fails_trc_fails | 4 +- ...stAPI_health_signer_grace_period_trc_fails | 2 +- .../mgmtapi/testdata/TestAPI_health_trc_error | 2 +- .../mgmtapi/testdata/TestAPI_health_trc_fails | 2 +- control/mgmtapi/types.gen.go | 254 +-- daemon/mgmtapi/api.go | 14 +- daemon/mgmtapi/client.gen.go | 81 +- daemon/mgmtapi/server.gen.go | 129 +- daemon/mgmtapi/types.gen.go | 59 +- dispatcher/mgmtapi/client.gen.go | 9 +- dispatcher/mgmtapi/server.gen.go | 34 +- dispatcher/mgmtapi/types.gen.go | 21 +- doc/build/dependencies.rst | 2 +- .../scion-pki/scion-pki_completion_bash.rst | 2 +- .../scion-pki/scion-pki_completion_zsh.rst | 6 +- doc/command/scion/scion_completion_bash.rst | 2 +- doc/command/scion/scion_completion_zsh.rst | 6 +- gateway/mgmtapi/client.gen.go | 9 +- gateway/mgmtapi/server.gen.go | 34 +- gateway/mgmtapi/types.gen.go | 21 +- go.mod | 129 +- go.sum | 568 +++--- go_deps.bzl | 1634 +++++++++++------ .../LICENSE | 21 + .../data/com_github_fsnotify_fsnotify/LICENSE | 47 +- .../LICENSE | 2 +- .../com_github_hashicorp_golang_lru/LICENSE | 2 + .../LICENSE | 0 .../data/com_github_labstack_echo_v4/LICENSE | 2 +- .../data/com_github_mohae_deepcopy/LICENSE | 21 + .../com_github_pelletier_go_toml_v2/LICENSE | 21 + .../com_github_perimeterx_marshmallow/LICENSE | 21 + licenses/data/in_gopkg_yaml_v3/LICENSE | 50 + .../data/org_uber_go_multierr/LICENSE.txt | 2 +- private/ca/api/BUILD.bazel | 1 + private/ca/api/client.gen.go | 95 +- private/ca/api/types.gen.go | 137 +- private/ca/renewal/grpc/delegating_handler.go | 45 +- .../renewal/grpc/delegating_handler_test.go | 11 +- private/ca/renewal/grpc/mock_grpc/mock.go | 2 +- private/mgmtapi/cppki/api/api.go | 24 +- private/mgmtapi/cppki/api/client.gen.go | 41 +- private/mgmtapi/cppki/api/server.gen.go | 77 +- private/mgmtapi/cppki/api/types.gen.go | 30 +- private/mgmtapi/health/api/client.gen.go | 4 +- private/mgmtapi/health/api/helpers.go | 10 +- private/mgmtapi/health/api/server.gen.go | 16 +- private/mgmtapi/health/api/types.gen.go | 82 +- private/mgmtapi/segments/api/api.go | 22 +- private/mgmtapi/segments/api/client.gen.go | 35 +- private/mgmtapi/segments/api/server.gen.go | 38 +- private/mgmtapi/segments/api/types.gen.go | 24 +- router/mgmtapi/api.go | 18 +- router/mgmtapi/client.gen.go | 19 +- router/mgmtapi/server.gen.go | 40 +- router/mgmtapi/types.gen.go | 75 +- rules_openapi/internal/bundle.bzl | 2 +- rules_openapi/tools/package.json | 8 +- rules_openapi/tools/yarn.lock | 1280 +++++++++---- spec/ca.gen.yml | 52 +- spec/control.gen.yml | 69 +- spec/cppki.gen.yml | 33 +- spec/daemon.gen.yml | 38 +- spec/router.gen.yml | 57 +- spec/segments.gen.yml | 33 +- 81 files changed, 3578 insertions(+), 2636 deletions(-) create mode 100644 licenses/data/com_github_apapsch_go_jsonmerge_v2/LICENSE rename licenses/data/{org_golang_x_xerrors => com_github_google_uuid}/LICENSE (96%) mode change 100755 => 100644 rename licenses/data/{com_github_ghodss_yaml => com_github_invopop_yaml}/LICENSE (100%) create mode 100644 licenses/data/com_github_mohae_deepcopy/LICENSE create mode 100644 licenses/data/com_github_pelletier_go_toml_v2/LICENSE create mode 100644 licenses/data/com_github_perimeterx_marshmallow/LICENSE create mode 100644 licenses/data/in_gopkg_yaml_v3/LICENSE diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 0744a03b5..1979d9ce6 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -32,7 +32,7 @@ steps: - mkdir -p /tmp/test-artifacts - cp go.mod go.sum go_deps.bzl /tmp/test-artifacts/ - make go_deps.bzl -B - - $(bazel info output_base 2>/dev/null)/external/go_sdk/bin/go mod tidy + - make go-mod-tidy - diff -u /tmp/test-artifacts/go.mod go.mod - diff -u /tmp/test-artifacts/go.sum go.sum - diff -u /tmp/test-artifacts/go_deps.bzl go_deps.bzl diff --git a/Makefile b/Makefile index f18b51a2a..355e27d70 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ -.PHONY: all antlr bazel build clean docker-images gazelle licenses mocks protobuf scion-topo test test-acceptance - +.PHONY: all antlr bazel clean docker-images gazelle go-mod-tidy licenses mocks protobuf scion-topo test test-integration GAZELLE_MODE?=fix GAZELLE_DIRS=. @@ -29,8 +28,11 @@ test: test-integration: bazel test --config=integration_all +go-mod-tidy: + bazel run --config=quiet @go_sdk//:bin/go -- mod tidy + go_deps.bzl: go.mod - bazel run //:gazelle -- update-repos -prune -from_file=go.mod -to_macro=go_deps.bzl%go_deps + bazel run --config=quiet //:gazelle -- update-repos -prune -from_file=go.mod -to_macro=go_deps.bzl%go_deps @# XXX(matzf): clean up; gazelle update-repose inconsistently inserts blank lines (see bazelbuild/bazel-gazelle#1088). @sed -e '/def go_deps/,$${/^$$/d}' -i go_deps.bzl diff --git a/WORKSPACE b/WORKSPACE index c8b7dc780..9936bb501 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -75,12 +75,12 @@ load("//:go_deps.bzl", "go_deps") go_deps() ## Explictly override xerrors: https://github.com/bazelbuild/bazel-gazelle/issues/1217 -go_repository( - name = "org_golang_x_xerrors", - importpath = "golang.org/x/xerrors", - sum = "h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=", - version = "v0.0.0-20200804184101-5ec99f83aff1", -) +# go_repository( +# name = "org_golang_x_xerrors", +# importpath = "golang.org/x/xerrors", +# sum = "h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=", +# version = "v0.0.0-20220907171357-04be3eba64a2", +# ) gazelle_dependencies() diff --git a/control/mgmtapi/api.go b/control/mgmtapi/api.go index 8bc9526e3..0d9d8d91c 100644 --- a/control/mgmtapi/api.go +++ b/control/mgmtapi/api.go @@ -95,16 +95,16 @@ type Server struct { func UnpackBeaconUsages(u beacon.Usage) []string { var names []string if u&beacon.UsageUpReg != 0 { - names = append(names, string(BeaconUsageUpRegistration)) + names = append(names, string(UpRegistration)) } if u&beacon.UsageDownReg != 0 { - names = append(names, string(BeaconUsageDownRegistration)) + names = append(names, string(DownRegistration)) } if u&beacon.UsageCoreReg != 0 { - names = append(names, string(BeaconUsageCoreRegistration)) + names = append(names, string(CoreRegistration)) } if u&beacon.UsageProp != 0 { - names = append(names, string(BeaconUsagePropagation)) + names = append(names, string(Propagation)) } return names } @@ -114,7 +114,7 @@ func (s *Server) GetBeacons(w http.ResponseWriter, r *http.Request, params GetBe q := beaconstorage.QueryParams{} var errs serrors.List if params.StartIsdAs != nil { - if ia, err := addr.ParseIA(string(*params.StartIsdAs)); err == nil { + if ia, err := addr.ParseIA(*params.StartIsdAs); err == nil { q.StartsAt = []addr.IA{ia} } else { errs = append(errs, serrors.WrapStr("parsing start_isd_as", err)) @@ -124,13 +124,13 @@ func (s *Server) GetBeacons(w http.ResponseWriter, r *http.Request, params GetBe var usage beacon.Usage for _, usageFlag := range *params.Usages { switch usageFlag { - case BeaconUsageCoreRegistration: + case CoreRegistration: usage |= beacon.UsageCoreReg - case BeaconUsageDownRegistration: + case DownRegistration: usage |= beacon.UsageDownReg - case BeaconUsagePropagation: + case Propagation: usage |= beacon.UsageProp - case BeaconUsageUpRegistration: + case UpRegistration: usage |= beacon.UsageUpReg default: errs = append(errs, serrors.New( @@ -167,7 +167,7 @@ func (s *Server) GetBeacons(w http.ResponseWriter, r *http.Request, params GetBe } if err := errs.ToError(); err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusBadRequest, Title: "malformed query parameters", @@ -177,7 +177,7 @@ func (s *Server) GetBeacons(w http.ResponseWriter, r *http.Request, params GetBe } results, err := s.Beacons.GetBeacons(r.Context(), &q) if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "error getting beacons", @@ -198,22 +198,22 @@ func (s *Server) GetBeacons(w http.ResponseWriter, r *http.Request, params GetBe if i != 0 { hops = append(hops, Hop{ Interface: int(as.HopEntry.HopField.ConsIngress), - IsdAs: IsdAs(as.Local.String())}) + IsdAs: as.Local.String(), + }) } hops = append(hops, Hop{ Interface: int(as.HopEntry.HopField.ConsEgress), - IsdAs: IsdAs(as.Local.String())}) + IsdAs: as.Local.String(), + }) } rep = append(rep, &Beacon{ Usages: usage, IngressInterface: int(result.Beacon.InIfId), - Segment: Segment{ - Id: SegmentID(segapi.SegID(s)), - LastUpdated: result.LastUpdated, - Timestamp: s.Info.Timestamp.UTC(), - Expiration: s.MinExpiry().UTC(), - Hops: hops, - }, + Id: segapi.SegID(s), + LastUpdated: result.LastUpdated, + Timestamp: s.Info.Timestamp.UTC(), + Expiration: s.MinExpiry().UTC(), + Hops: hops, }) } // Sort the results. @@ -225,7 +225,7 @@ func (s *Server) GetBeacons(w http.ResponseWriter, r *http.Request, params GetBe enc := json.NewEncoder(w) enc.SetIndent("", " ") if err := enc.Encode(map[string][]*Beacon{"beacons": rep}); err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "unable to marshal response", @@ -256,18 +256,18 @@ func sortFactory(sortParam *GetBeaconsParamsSort) (func(b []*Beacon) sort.Interf switch by { case "expiration_time": less = func(a, b *Beacon) bool { - return a.Segment.Expiration.Before(b.Segment.Expiration) + return a.Expiration.Before(b.Expiration) } case "info_time": less = func(a, b *Beacon) bool { - return a.Segment.Timestamp.Before(b.Segment.Timestamp) + return a.Timestamp.Before(b.Timestamp) } case "start_isd_as": less = func(a, b *Beacon) bool { - if len(a.Segment.Hops) == 0 || len(b.Segment.Hops) == 0 { - return len(a.Segment.Hops) < len(b.Segment.Hops) + if len(a.Hops) == 0 || len(b.Hops) == 0 { + return len(a.Hops) < len(b.Hops) } - return a.Segment.Hops[0].IsdAs < b.Segment.Hops[0].IsdAs + return a.Hops[0].IsdAs < b.Hops[0].IsdAs } case "last_updated": less = func(a, b *Beacon) bool { @@ -288,9 +288,9 @@ func sortFactory(sortParam *GetBeaconsParamsSort) (func(b []*Beacon) sort.Interf }, nil } func (s *Server) GetBeacon(w http.ResponseWriter, r *http.Request, segmentId SegmentID) { - id, err := hex.DecodeString(string(segmentId)) + id, err := hex.DecodeString(segmentId) if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusBadRequest, Title: "error decoding segment id", @@ -303,7 +303,7 @@ func (s *Server) GetBeacon(w http.ResponseWriter, r *http.Request, segmentId Seg } results, err := s.Beacons.GetBeacons(r.Context(), &q) if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "error getting beacons", @@ -312,7 +312,7 @@ func (s *Server) GetBeacon(w http.ResponseWriter, r *http.Request, segmentId Seg return } if len(results) == 0 { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(fmt.Sprintf( "no beacon matched provided segment ID: %s", segmentId, @@ -324,7 +324,7 @@ func (s *Server) GetBeacon(w http.ResponseWriter, r *http.Request, segmentId Seg return } if len(results) > 1 { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(fmt.Sprintf( "%d beacons matched provided segment ID: %s", len(results), @@ -346,29 +346,29 @@ func (s *Server) GetBeacon(w http.ResponseWriter, r *http.Request, segmentId Seg if i != 0 { hops = append(hops, Hop{ Interface: int(as.HopEntry.HopField.ConsIngress), - IsdAs: IsdAs(as.Local.String())}) + IsdAs: as.Local.String(), + }) } hops = append(hops, Hop{ Interface: int(as.HopEntry.HopField.ConsEgress), - IsdAs: IsdAs(as.Local.String())}) + IsdAs: as.Local.String(), + }) } res := map[string]Beacon{ "beacon": { Usages: usage, IngressInterface: int(results[0].Beacon.InIfId), - Segment: Segment{ - Id: SegmentID(segapi.SegID(seg)), - LastUpdated: results[0].LastUpdated, - Timestamp: seg.Info.Timestamp.UTC(), - Expiration: seg.MinExpiry().UTC(), - Hops: hops, - }, + Id: segapi.SegID(seg), + LastUpdated: results[0].LastUpdated, + Timestamp: seg.Info.Timestamp.UTC(), + Expiration: seg.MinExpiry().UTC(), + Hops: hops, }, } enc := json.NewEncoder(w) enc.SetIndent("", " ") if err := enc.Encode(res); err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "unable to marshal response", @@ -381,9 +381,9 @@ func (s *Server) GetBeacon(w http.ResponseWriter, r *http.Request, segmentId Seg func (s *Server) GetBeaconBlob(w http.ResponseWriter, r *http.Request, segmentId SegmentID) { w.Header().Set("Content-Type", "application/x-pem-file") - id, err := hex.DecodeString(string(segmentId)) + id, err := hex.DecodeString(segmentId) if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusBadRequest, Title: "error decoding segment id", @@ -396,7 +396,7 @@ func (s *Server) GetBeaconBlob(w http.ResponseWriter, r *http.Request, segmentId } results, err := s.Beacons.GetBeacons(r.Context(), &q) if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "error getting beacons", @@ -405,7 +405,7 @@ func (s *Server) GetBeaconBlob(w http.ResponseWriter, r *http.Request, segmentId return } if len(results) == 0 { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(fmt.Sprintf( "no beacon matched provided segment ID: %s", segmentId, @@ -417,7 +417,7 @@ func (s *Server) GetBeaconBlob(w http.ResponseWriter, r *http.Request, segmentId return } if len(results) > 1 { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(fmt.Sprintf( "%d beacons matched provided segment ID: %s", len(results), @@ -433,7 +433,7 @@ func (s *Server) GetBeaconBlob(w http.ResponseWriter, r *http.Request, segmentId segment := results[0].Beacon.Segment bytes, err := proto.Marshal(seg.PathSegmentToPB(segment)) if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "unable to marshal beacon", @@ -446,7 +446,7 @@ func (s *Server) GetBeaconBlob(w http.ResponseWriter, r *http.Request, segmentId Bytes: bytes, } if err := pem.Encode(&buf, b); err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "unable to marshal response", @@ -461,25 +461,25 @@ func (s *Server) GetBeaconBlob(w http.ResponseWriter, r *http.Request, segmentId func (s *Server) GetSegments(w http.ResponseWriter, r *http.Request, params GetSegmentsParams) { p := segapi.GetSegmentsParams{ - StartIsdAs: (*segapi.IsdAs)(params.StartIsdAs), - EndIsdAs: (*segapi.IsdAs)(params.EndIsdAs), + StartIsdAs: params.StartIsdAs, + EndIsdAs: params.EndIsdAs, } s.SegmentsServer.GetSegments(w, r, p) } func (s *Server) GetSegment(w http.ResponseWriter, r *http.Request, id SegmentID) { - s.SegmentsServer.GetSegment(w, r, segapi.SegmentID(id)) + s.SegmentsServer.GetSegment(w, r, id) } func (s *Server) GetSegmentBlob(w http.ResponseWriter, r *http.Request, id SegmentID) { - s.SegmentsServer.GetSegmentBlob(w, r, segapi.SegmentID(id)) + s.SegmentsServer.GetSegmentBlob(w, r, id) } // GetCertificates lists the certificate chains. func (s *Server) GetCertificates(w http.ResponseWriter, r *http.Request, params GetCertificatesParams) { cppkiParams := cppkiapi.GetCertificatesParams{ - IsdAs: (*cppkiapi.IsdAs)(params.IsdAs), + IsdAs: params.IsdAs, ValidAt: params.ValidAt, All: params.All, } @@ -488,19 +488,19 @@ func (s *Server) GetCertificates(w http.ResponseWriter, // GetCertificate lists the certificate chain for a given ChainID. func (s *Server) GetCertificate(w http.ResponseWriter, r *http.Request, chainID ChainID) { - s.CPPKIServer.GetCertificate(w, r, cppkiapi.ChainID(chainID)) + s.CPPKIServer.GetCertificate(w, r, chainID) } // GetCertificateBlob gnerates a certificate chain blob response encoded as PEM for a given chainId. func (s *Server) GetCertificateBlob(w http.ResponseWriter, r *http.Request, chainID ChainID) { - s.CPPKIServer.GetCertificateBlob(w, r, cppkiapi.ChainID(chainID)) + s.CPPKIServer.GetCertificateBlob(w, r, chainID) } // GetCa gets the CA info. func (s *Server) GetCa(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") if s.CA.PolicyGen == nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef("This instance is not configured with CA capability"), Status: http.StatusNotImplemented, Title: "Not a CA", @@ -511,7 +511,7 @@ func (s *Server) GetCa(w http.ResponseWriter, r *http.Request) { p, err := s.CA.PolicyGen.Generate(r.Context()) if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "No active signer", @@ -521,7 +521,7 @@ func (s *Server) GetCa(w http.ResponseWriter, r *http.Request) { } ia, err := cppki.ExtractIA(p.Certificate.Subject) if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "Unable to extract ISD-AS", @@ -538,14 +538,14 @@ func (s *Server) GetCa(w http.ResponseWriter, r *http.Request) { ChainLifetime: p.Validity.String(), }, Subject: Subject{ - IsdAs: IsdAs(ia.String()), + IsdAs: ia.String(), }, - SubjectKeyId: SubjectKeyID(fmt.Sprintf("% X", p.Certificate.SubjectKeyId)), + SubjectKeyId: fmt.Sprintf("% X", p.Certificate.SubjectKeyId), } enc := json.NewEncoder(w) enc.SetIndent("", " ") if err := enc.Encode(rep); err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "unable to marshal response", @@ -599,7 +599,7 @@ func (s *Server) GetSigner(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") p, err := s.Signer.SignerGen.Generate(r.Context()) if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "Unable to get signer", @@ -610,9 +610,9 @@ func (s *Server) GetSigner(w http.ResponseWriter, r *http.Request) { rep := Signer{ AsCertificate: Certificate{ DistinguishedName: p.Subject.String(), - IsdAs: IsdAs(p.IA.String()), + IsdAs: p.IA.String(), SubjectKeyAlgo: p.Algorithm.String(), - SubjectKeyId: SubjectKeyID(fmt.Sprintf("% X", p.SubjectKeyID)), + SubjectKeyId: fmt.Sprintf("% X", p.SubjectKeyID), Validity: Validity{ NotAfter: p.ChainValidity.NotAfter, NotBefore: p.ChainValidity.NotBefore, @@ -629,7 +629,7 @@ func (s *Server) GetSigner(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) enc.SetIndent("", " ") if err := enc.Encode(rep); err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "unable to marshal response", @@ -643,7 +643,7 @@ func (s *Server) GetSigner(w http.ResponseWriter, r *http.Request) { func (s *Server) GetSignerChain(w http.ResponseWriter, r *http.Request) { p, err := s.Signer.SignerGen.Generate(r.Context()) if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "unable to get signer", @@ -653,7 +653,7 @@ func (s *Server) GetSignerChain(w http.ResponseWriter, r *http.Request) { } var buf bytes.Buffer if len(p.Chain) == 0 { - Error(w, Problem{ + ErrorResponse(w, Problem{ Status: http.StatusInternalServerError, Title: "no certificates available", Type: api.StringRef(api.InternalError), @@ -662,7 +662,7 @@ func (s *Server) GetSignerChain(w http.ResponseWriter, r *http.Request) { } for _, cert := range p.Chain { if err := pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}); err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "unable to marshal response", @@ -685,52 +685,44 @@ func (s *Server) GetHealth(w http.ResponseWriter, r *http.Request) { signerHealth := s.Healther.GetSignerHealth(r.Context()) signerCheck := Check{ - Status: StatusPassing, + Status: Passing, Name: "valid signer available", } switch { case signerHealth.SignerMissing: - signerCheck.Status = StatusFailing + signerCheck.Status = Failing if signerHealth.SignerMissingDetail != "" { signerCheck.Detail = api.StringRef(signerHealth.SignerMissingDetail) } case time.Until(signerHealth.Expiration) <= 0: - signerCheck.Status = StatusFailing + signerCheck.Status = Failing signerCheck.Detail = api.StringRef("signer certificate has expired") signerCheck.Data = CheckData{ - AdditionalProperties: map[string]interface{}{ - "expires_at": signerHealth.Expiration.Format(time.RFC3339), - }, + "expires_at": signerHealth.Expiration.Format(time.RFC3339), } case signerHealth.InGrace: - signerCheck.Status = StatusDegraded + signerCheck.Status = Degraded signerCheck.Data = CheckData{ - AdditionalProperties: map[string]interface{}{ - "expires_at": signerHealth.Expiration.Format(time.RFC3339), - "in_grace": true, - }, + "expires_at": signerHealth.Expiration.Format(time.RFC3339), + "in_grace": true, } signerCheck.Detail = api.StringRef(`signer certificate is authenticated by TRC in grace period`) case time.Until(signerHealth.Expiration) < 6*time.Hour: - signerCheck.Status = StatusDegraded + signerCheck.Status = Degraded signerCheck.Data = CheckData{ - AdditionalProperties: map[string]interface{}{ - "expires_at": signerHealth.Expiration.Format(time.RFC3339), - }, + "expires_at": signerHealth.Expiration.Format(time.RFC3339), } signerCheck.Detail = api.StringRef("signer certificate is close to expiration") default: signerCheck.Data = CheckData{ - AdditionalProperties: map[string]interface{}{ - "expires_at": signerHealth.Expiration.Format(time.RFC3339), - }, + "expires_at": signerHealth.Expiration.Format(time.RFC3339), } } checks = append(checks, signerCheck) trcCheck := Check{ - Status: StatusFailing, + Status: Failing, Name: "TRC for local ISD available", } trcHealthData := s.Healther.GetTRCHealth(r.Context()) @@ -738,29 +730,25 @@ func (s *Server) GetHealth(w http.ResponseWriter, r *http.Request) { trcCheck.Detail = api.StringRef(trcHealthData.TRCNotFoundDetail) } if !trcHealthData.TRCNotFound { - trcCheck.Status = StatusPassing + trcCheck.Status = Passing trcCheck.Data = CheckData{ - AdditionalProperties: map[string]interface{}{ - "base_number": trcHealthData.TRCID.Base, - "serial_number": trcHealthData.TRCID.Serial, - "isd": trcHealthData.TRCID.ISD, - }, + "base_number": trcHealthData.TRCID.Base, + "serial_number": trcHealthData.TRCID.Serial, + "isd": trcHealthData.TRCID.ISD, } } checks = append(checks, trcCheck) if status, ok := s.Healther.GetCAHealth(r.Context()); ok { caCheck := Check{ - Status: StatusDegraded, + Status: Degraded, Name: "CPPKI CA Connection", } if status == Available { - caCheck.Status = StatusPassing + caCheck.Status = Passing } caCheck.Data = CheckData{ - AdditionalProperties: map[string]interface{}{ - "status": status, - }, + "status": status, } checks = append(checks, caCheck) } @@ -781,7 +769,7 @@ func (s *Server) GetHealth(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) enc.SetIndent("", " ") if err := enc.Encode(rep); err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "unable to marshal response", @@ -792,7 +780,7 @@ func (s *Server) GetHealth(w http.ResponseWriter, r *http.Request) { } // Error creates an detailed error response. -func Error(w http.ResponseWriter, p Problem) { +func ErrorResponse(w http.ResponseWriter, p Problem) { w.Header().Set("Content-Type", "application/problem+json") w.WriteHeader(p.Status) enc := json.NewEncoder(w) diff --git a/control/mgmtapi/api_test.go b/control/mgmtapi/api_test.go index 71b7f6643..29e938be2 100644 --- a/control/mgmtapi/api_test.go +++ b/control/mgmtapi/api_test.go @@ -69,7 +69,7 @@ func TestAPI(t *testing.T) { } bs.EXPECT().GetBeacons( gomock.Any(), - &beacon.QueryParams{}, + matchQuery(&beacon.QueryParams{}), ).AnyTimes().Return(beacons, nil) return api.Handler(s) }, @@ -84,7 +84,7 @@ func TestAPI(t *testing.T) { } bs.EXPECT().GetBeacons( gomock.Any(), - &beacon.QueryParams{}, + matchQuery(&beacon.QueryParams{}), ).Times(0).Return(beacons, nil) return api.Handler(s) }, @@ -99,7 +99,7 @@ func TestAPI(t *testing.T) { } bs.EXPECT().GetBeacons( gomock.Any(), - &beacon.QueryParams{}, + matchQuery(&beacon.QueryParams{}), ).Times(1).Return(beacons, nil) return api.Handler(s) }, @@ -114,7 +114,7 @@ func TestAPI(t *testing.T) { } bs.EXPECT().GetBeacons( gomock.Any(), - &beacon.QueryParams{}, + matchQuery(&beacon.QueryParams{}), ).Times(1).Return(beacons, nil) return api.Handler(s) }, @@ -129,7 +129,7 @@ func TestAPI(t *testing.T) { } bs.EXPECT().GetBeacons( gomock.Any(), - &beacon.QueryParams{}, + gomock.Any(), ).Times(0).Return(beacons, nil) return api.Handler(s) }, @@ -144,9 +144,9 @@ func TestAPI(t *testing.T) { } bs.EXPECT().GetBeacons( gomock.Any(), - &beacon.QueryParams{ + matchQuery(&beacon.QueryParams{ Usages: []beaconlib.Usage{beaconlib.UsageDownReg | beaconlib.UsageUpReg}, - }, + }), ).Times(1).Return(beacons[:1], nil) return api.Handler(s) }, @@ -976,3 +976,37 @@ func createBeacons(t *testing.T) []beacon.Beacon { }, } } + +type queryMatcher struct { + query *beacon.QueryParams + creationTime time.Time +} + +// matchQuery creates a matcher that matches the QueryParams with validAt time +// that needs to be within 10s of the creation. +func matchQuery(q *beacon.QueryParams) gomock.Matcher { + return queryMatcher{ + query: q, + creationTime: time.Now(), + } +} + +func (m queryMatcher) Matches(x any) bool { + p, ok := x.(*beacon.QueryParams) + if !ok { + return false + } + validAt := p.ValidAt + // check that validAt is roughly the same, be lenient and give a 10s window, + // for CI. + if !assert.WithinDuration(&testing.T{}, m.creationTime, validAt, 10*time.Second) { + return false + } + p.ValidAt = time.Time{} + // return whether the rest is equal. + return assert.ObjectsAreEqual(m.query, p) +} + +func (m queryMatcher) String() string { + return fmt.Sprintf("%v with ValidAt around %s", m.query, m.creationTime) +} diff --git a/control/mgmtapi/client.gen.go b/control/mgmtapi/client.gen.go index 09a16fec9..bcc8495fa 100644 --- a/control/mgmtapi/client.gen.go +++ b/control/mgmtapi/client.gen.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -1530,6 +1529,7 @@ type GetCertificatesResponse struct { Body []byte HTTPResponse *http.Response JSON200 *[]ChainBrief + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -1552,6 +1552,7 @@ type GetCertificateResponse struct { Body []byte HTTPResponse *http.Response JSON200 *Chain + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -1573,6 +1574,7 @@ func (r GetCertificateResponse) StatusCode() int { type GetCertificateBlobResponse struct { Body []byte HTTPResponse *http.Response + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -1708,6 +1710,7 @@ type GetSegmentsResponse struct { Body []byte HTTPResponse *http.Response JSON200 *[]SegmentBrief + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -1730,6 +1733,7 @@ type GetSegmentResponse struct { Body []byte HTTPResponse *http.Response JSON200 *Segment + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -1751,6 +1755,7 @@ func (r GetSegmentResponse) StatusCode() int { type GetSegmentBlobResponse struct { Body []byte HTTPResponse *http.Response + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -2104,7 +2109,7 @@ func (c *ClientWithResponses) GetTrcBlobWithResponse(ctx context.Context, isd in // ParseGetBeaconsResponse parses an HTTP response from a GetBeaconsWithResponse call func ParseGetBeaconsResponse(rsp *http.Response) (*GetBeaconsResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2139,7 +2144,7 @@ func ParseGetBeaconsResponse(rsp *http.Response) (*GetBeaconsResponse, error) { // ParseGetBeaconResponse parses an HTTP response from a GetBeaconWithResponse call func ParseGetBeaconResponse(rsp *http.Response) (*GetBeaconResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2172,7 +2177,7 @@ func ParseGetBeaconResponse(rsp *http.Response) (*GetBeaconResponse, error) { // ParseGetBeaconBlobResponse parses an HTTP response from a GetBeaconBlobWithResponse call func ParseGetBeaconBlobResponse(rsp *http.Response) (*GetBeaconBlobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2198,7 +2203,7 @@ func ParseGetBeaconBlobResponse(rsp *http.Response) (*GetBeaconBlobResponse, err // ParseGetCaResponse parses an HTTP response from a GetCaWithResponse call func ParseGetCaResponse(rsp *http.Response) (*GetCaResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2231,7 +2236,7 @@ func ParseGetCaResponse(rsp *http.Response) (*GetCaResponse, error) { // ParseGetCertificatesResponse parses an HTTP response from a GetCertificatesWithResponse call func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2250,6 +2255,13 @@ func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -2257,7 +2269,7 @@ func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, // ParseGetCertificateResponse parses an HTTP response from a GetCertificateWithResponse call func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2276,6 +2288,13 @@ func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, e } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -2283,7 +2302,7 @@ func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, e // ParseGetCertificateBlobResponse parses an HTTP response from a GetCertificateBlobWithResponse call func ParseGetCertificateBlobResponse(rsp *http.Response) (*GetCertificateBlobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2294,12 +2313,22 @@ func ParseGetCertificateBlobResponse(rsp *http.Response) (*GetCertificateBlobRes HTTPResponse: rsp, } + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + return response, nil } // ParseGetConfigResponse parses an HTTP response from a GetConfigWithResponse call func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2325,7 +2354,7 @@ func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { // ParseGetHealthResponse parses an HTTP response from a GetHealthWithResponse call func ParseGetHealthResponse(rsp *http.Response) (*GetHealthResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2358,7 +2387,7 @@ func ParseGetHealthResponse(rsp *http.Response) (*GetHealthResponse, error) { // ParseGetInfoResponse parses an HTTP response from a GetInfoWithResponse call func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2384,7 +2413,7 @@ func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { // ParseGetLogLevelResponse parses an HTTP response from a GetLogLevelWithResponse call func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2417,7 +2446,7 @@ func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) // ParseSetLogLevelResponse parses an HTTP response from a SetLogLevelWithResponse call func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2450,7 +2479,7 @@ func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) // ParseGetSegmentsResponse parses an HTTP response from a GetSegmentsWithResponse call func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2469,6 +2498,13 @@ func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -2476,7 +2512,7 @@ func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) // ParseGetSegmentResponse parses an HTTP response from a GetSegmentWithResponse call func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2495,6 +2531,13 @@ func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -2502,7 +2545,7 @@ func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { // ParseGetSegmentBlobResponse parses an HTTP response from a GetSegmentBlobWithResponse call func ParseGetSegmentBlobResponse(rsp *http.Response) (*GetSegmentBlobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2513,12 +2556,22 @@ func ParseGetSegmentBlobResponse(rsp *http.Response) (*GetSegmentBlobResponse, e HTTPResponse: rsp, } + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + return response, nil } // ParseGetSignerResponse parses an HTTP response from a GetSignerWithResponse call func ParseGetSignerResponse(rsp *http.Response) (*GetSignerResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2551,7 +2604,7 @@ func ParseGetSignerResponse(rsp *http.Response) (*GetSignerResponse, error) { // ParseGetSignerChainResponse parses an HTTP response from a GetSignerChainWithResponse call func ParseGetSignerChainResponse(rsp *http.Response) (*GetSignerChainResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2577,7 +2630,7 @@ func ParseGetSignerChainResponse(rsp *http.Response) (*GetSignerChainResponse, e // ParseGetTopologyResponse parses an HTTP response from a GetTopologyWithResponse call func ParseGetTopologyResponse(rsp *http.Response) (*GetTopologyResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2610,7 +2663,7 @@ func ParseGetTopologyResponse(rsp *http.Response) (*GetTopologyResponse, error) // ParseGetTrcsResponse parses an HTTP response from a GetTrcsWithResponse call func ParseGetTrcsResponse(rsp *http.Response) (*GetTrcsResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2643,7 +2696,7 @@ func ParseGetTrcsResponse(rsp *http.Response) (*GetTrcsResponse, error) { // ParseGetTrcResponse parses an HTTP response from a GetTrcWithResponse call func ParseGetTrcResponse(rsp *http.Response) (*GetTrcResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -2676,7 +2729,7 @@ func ParseGetTrcResponse(rsp *http.Response) (*GetTrcResponse, error) { // ParseGetTrcBlobResponse parses an HTTP response from a GetTrcBlobWithResponse call func ParseGetTrcBlobResponse(rsp *http.Response) (*GetTrcBlobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err diff --git a/control/mgmtapi/server.gen.go b/control/mgmtapi/server.gen.go index c085950e3..d30513ea9 100644 --- a/control/mgmtapi/server.gen.go +++ b/control/mgmtapi/server.gen.go @@ -85,7 +85,7 @@ type ServerInterfaceWrapper struct { ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) } -type MiddlewareFunc func(http.HandlerFunc) http.HandlerFunc +type MiddlewareFunc func(http.Handler) http.Handler // GetBeacons operation middleware func (siw *ServerInterfaceWrapper) GetBeacons(w http.ResponseWriter, r *http.Request) { @@ -97,9 +97,6 @@ func (siw *ServerInterfaceWrapper) GetBeacons(w http.ResponseWriter, r *http.Req var params GetBeaconsParams // ------------- Optional query parameter "start_isd_as" ------------- - if paramValue := r.URL.Query().Get("start_isd_as"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "start_isd_as", r.URL.Query(), ¶ms.StartIsdAs) if err != nil { @@ -108,9 +105,6 @@ func (siw *ServerInterfaceWrapper) GetBeacons(w http.ResponseWriter, r *http.Req } // ------------- Optional query parameter "usages" ------------- - if paramValue := r.URL.Query().Get("usages"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "usages", r.URL.Query(), ¶ms.Usages) if err != nil { @@ -119,9 +113,6 @@ func (siw *ServerInterfaceWrapper) GetBeacons(w http.ResponseWriter, r *http.Req } // ------------- Optional query parameter "ingress_interface" ------------- - if paramValue := r.URL.Query().Get("ingress_interface"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "ingress_interface", r.URL.Query(), ¶ms.IngressInterface) if err != nil { @@ -130,9 +121,6 @@ func (siw *ServerInterfaceWrapper) GetBeacons(w http.ResponseWriter, r *http.Req } // ------------- Optional query parameter "valid_at" ------------- - if paramValue := r.URL.Query().Get("valid_at"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "valid_at", r.URL.Query(), ¶ms.ValidAt) if err != nil { @@ -141,9 +129,6 @@ func (siw *ServerInterfaceWrapper) GetBeacons(w http.ResponseWriter, r *http.Req } // ------------- Optional query parameter "all" ------------- - if paramValue := r.URL.Query().Get("all"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "all", r.URL.Query(), ¶ms.All) if err != nil { @@ -152,9 +137,6 @@ func (siw *ServerInterfaceWrapper) GetBeacons(w http.ResponseWriter, r *http.Req } // ------------- Optional query parameter "desc" ------------- - if paramValue := r.URL.Query().Get("desc"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "desc", r.URL.Query(), ¶ms.Desc) if err != nil { @@ -163,9 +145,6 @@ func (siw *ServerInterfaceWrapper) GetBeacons(w http.ResponseWriter, r *http.Req } // ------------- Optional query parameter "sort" ------------- - if paramValue := r.URL.Query().Get("sort"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "sort", r.URL.Query(), ¶ms.Sort) if err != nil { @@ -173,15 +152,15 @@ func (siw *ServerInterfaceWrapper) GetBeacons(w http.ResponseWriter, r *http.Req return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetBeacons(w, r, params) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetBeacon operation middleware @@ -193,21 +172,21 @@ func (siw *ServerInterfaceWrapper) GetBeacon(w http.ResponseWriter, r *http.Requ // ------------- Path parameter "segment-id" ------------- var segmentId SegmentID - err = runtime.BindStyledParameter("simple", false, "segment-id", chi.URLParam(r, "segment-id"), &segmentId) + err = runtime.BindStyledParameterWithLocation("simple", false, "segment-id", runtime.ParamLocationPath, chi.URLParam(r, "segment-id"), &segmentId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "segment-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetBeacon(w, r, segmentId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetBeaconBlob operation middleware @@ -219,36 +198,36 @@ func (siw *ServerInterfaceWrapper) GetBeaconBlob(w http.ResponseWriter, r *http. // ------------- Path parameter "segment-id" ------------- var segmentId SegmentID - err = runtime.BindStyledParameter("simple", false, "segment-id", chi.URLParam(r, "segment-id"), &segmentId) + err = runtime.BindStyledParameterWithLocation("simple", false, "segment-id", runtime.ParamLocationPath, chi.URLParam(r, "segment-id"), &segmentId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "segment-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetBeaconBlob(w, r, segmentId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetCa operation middleware func (siw *ServerInterfaceWrapper) GetCa(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCa(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetCertificates operation middleware @@ -261,9 +240,6 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt var params GetCertificatesParams // ------------- Optional query parameter "isd_as" ------------- - if paramValue := r.URL.Query().Get("isd_as"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "isd_as", r.URL.Query(), ¶ms.IsdAs) if err != nil { @@ -272,9 +248,6 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt } // ------------- Optional query parameter "valid_at" ------------- - if paramValue := r.URL.Query().Get("valid_at"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "valid_at", r.URL.Query(), ¶ms.ValidAt) if err != nil { @@ -283,9 +256,6 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt } // ------------- Optional query parameter "all" ------------- - if paramValue := r.URL.Query().Get("all"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "all", r.URL.Query(), ¶ms.All) if err != nil { @@ -293,15 +263,15 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificates(w, r, params) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetCertificate operation middleware @@ -313,21 +283,21 @@ func (siw *ServerInterfaceWrapper) GetCertificate(w http.ResponseWriter, r *http // ------------- Path parameter "chain-id" ------------- var chainId ChainID - err = runtime.BindStyledParameter("simple", false, "chain-id", chi.URLParam(r, "chain-id"), &chainId) + err = runtime.BindStyledParameterWithLocation("simple", false, "chain-id", runtime.ParamLocationPath, chi.URLParam(r, "chain-id"), &chainId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "chain-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificate(w, r, chainId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetCertificateBlob operation middleware @@ -339,96 +309,96 @@ func (siw *ServerInterfaceWrapper) GetCertificateBlob(w http.ResponseWriter, r * // ------------- Path parameter "chain-id" ------------- var chainId ChainID - err = runtime.BindStyledParameter("simple", false, "chain-id", chi.URLParam(r, "chain-id"), &chainId) + err = runtime.BindStyledParameterWithLocation("simple", false, "chain-id", runtime.ParamLocationPath, chi.URLParam(r, "chain-id"), &chainId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "chain-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificateBlob(w, r, chainId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetConfig operation middleware func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetConfig(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetHealth operation middleware func (siw *ServerInterfaceWrapper) GetHealth(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetHealth(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetInfo operation middleware func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInfo(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetLogLevel operation middleware func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetLogLevel(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // SetLogLevel operation middleware func (siw *ServerInterfaceWrapper) SetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetLogLevel(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetSegments operation middleware @@ -441,9 +411,6 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re var params GetSegmentsParams // ------------- Optional query parameter "start_isd_as" ------------- - if paramValue := r.URL.Query().Get("start_isd_as"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "start_isd_as", r.URL.Query(), ¶ms.StartIsdAs) if err != nil { @@ -452,9 +419,6 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re } // ------------- Optional query parameter "end_isd_as" ------------- - if paramValue := r.URL.Query().Get("end_isd_as"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "end_isd_as", r.URL.Query(), ¶ms.EndIsdAs) if err != nil { @@ -462,15 +426,15 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegments(w, r, params) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetSegment operation middleware @@ -482,21 +446,21 @@ func (siw *ServerInterfaceWrapper) GetSegment(w http.ResponseWriter, r *http.Req // ------------- Path parameter "segment-id" ------------- var segmentId SegmentID - err = runtime.BindStyledParameter("simple", false, "segment-id", chi.URLParam(r, "segment-id"), &segmentId) + err = runtime.BindStyledParameterWithLocation("simple", false, "segment-id", runtime.ParamLocationPath, chi.URLParam(r, "segment-id"), &segmentId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "segment-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegment(w, r, segmentId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetSegmentBlob operation middleware @@ -508,66 +472,66 @@ func (siw *ServerInterfaceWrapper) GetSegmentBlob(w http.ResponseWriter, r *http // ------------- Path parameter "segment-id" ------------- var segmentId SegmentID - err = runtime.BindStyledParameter("simple", false, "segment-id", chi.URLParam(r, "segment-id"), &segmentId) + err = runtime.BindStyledParameterWithLocation("simple", false, "segment-id", runtime.ParamLocationPath, chi.URLParam(r, "segment-id"), &segmentId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "segment-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegmentBlob(w, r, segmentId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetSigner operation middleware func (siw *ServerInterfaceWrapper) GetSigner(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSigner(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetSignerChain operation middleware func (siw *ServerInterfaceWrapper) GetSignerChain(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSignerChain(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetTopology operation middleware func (siw *ServerInterfaceWrapper) GetTopology(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTopology(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetTrcs operation middleware @@ -580,9 +544,6 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques var params GetTrcsParams // ------------- Optional query parameter "isd" ------------- - if paramValue := r.URL.Query().Get("isd"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", false, false, "isd", r.URL.Query(), ¶ms.Isd) if err != nil { @@ -591,9 +552,6 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques } // ------------- Optional query parameter "all" ------------- - if paramValue := r.URL.Query().Get("all"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "all", r.URL.Query(), ¶ms.All) if err != nil { @@ -601,15 +559,15 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcs(w, r, params) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetTrc operation middleware @@ -621,7 +579,7 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request // ------------- Path parameter "isd" ------------- var isd int - err = runtime.BindStyledParameter("simple", false, "isd", chi.URLParam(r, "isd"), &isd) + err = runtime.BindStyledParameterWithLocation("simple", false, "isd", runtime.ParamLocationPath, chi.URLParam(r, "isd"), &isd) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "isd", Err: err}) return @@ -630,7 +588,7 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request // ------------- Path parameter "base" ------------- var base int - err = runtime.BindStyledParameter("simple", false, "base", chi.URLParam(r, "base"), &base) + err = runtime.BindStyledParameterWithLocation("simple", false, "base", runtime.ParamLocationPath, chi.URLParam(r, "base"), &base) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "base", Err: err}) return @@ -639,21 +597,21 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request // ------------- Path parameter "serial" ------------- var serial int - err = runtime.BindStyledParameter("simple", false, "serial", chi.URLParam(r, "serial"), &serial) + err = runtime.BindStyledParameterWithLocation("simple", false, "serial", runtime.ParamLocationPath, chi.URLParam(r, "serial"), &serial) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "serial", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrc(w, r, isd, base, serial) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetTrcBlob operation middleware @@ -665,7 +623,7 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req // ------------- Path parameter "isd" ------------- var isd int - err = runtime.BindStyledParameter("simple", false, "isd", chi.URLParam(r, "isd"), &isd) + err = runtime.BindStyledParameterWithLocation("simple", false, "isd", runtime.ParamLocationPath, chi.URLParam(r, "isd"), &isd) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "isd", Err: err}) return @@ -674,7 +632,7 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req // ------------- Path parameter "base" ------------- var base int - err = runtime.BindStyledParameter("simple", false, "base", chi.URLParam(r, "base"), &base) + err = runtime.BindStyledParameterWithLocation("simple", false, "base", runtime.ParamLocationPath, chi.URLParam(r, "base"), &base) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "base", Err: err}) return @@ -683,21 +641,21 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req // ------------- Path parameter "serial" ------------- var serial int - err = runtime.BindStyledParameter("simple", false, "serial", chi.URLParam(r, "serial"), &serial) + err = runtime.BindStyledParameterWithLocation("simple", false, "serial", runtime.ParamLocationPath, chi.URLParam(r, "serial"), &serial) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "serial", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcBlob(w, r, isd, base, serial) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } type UnescapedCookieParamError struct { @@ -713,16 +671,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshalingParamError struct { +type UnmarshallingParamError struct { ParamName string Err error } -func (e *UnmarshalingParamError) Error() string { - return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshallingParamError) Error() string { + return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshalingParamError) Unwrap() error { +func (e *UnmarshallingParamError) Unwrap() error { return e.Err } diff --git a/control/mgmtapi/testdata/TestAPI_beacon b/control/mgmtapi/testdata/TestAPI_beacon index 7969bf593..8f4c65c16 100644 --- a/control/mgmtapi/testdata/TestAPI_beacon +++ b/control/mgmtapi/testdata/TestAPI_beacon @@ -16,9 +16,9 @@ } ], "id": "6e1f2ac35d1382a6064600007f9f270f6506c0b3453ee50423b5f1a73de53345", + "ingress_interface": 2, "last_updated": "2021-01-02T08:00:00Z", "timestamp": "2021-01-01T08:00:00Z", - "ingress_interface": 2, "usages": [ "up_registration", "down_registration" diff --git a/control/mgmtapi/testdata/TestAPI_beacon_id_prefix b/control/mgmtapi/testdata/TestAPI_beacon_id_prefix index 7969bf593..8f4c65c16 100644 --- a/control/mgmtapi/testdata/TestAPI_beacon_id_prefix +++ b/control/mgmtapi/testdata/TestAPI_beacon_id_prefix @@ -16,9 +16,9 @@ } ], "id": "6e1f2ac35d1382a6064600007f9f270f6506c0b3453ee50423b5f1a73de53345", + "ingress_interface": 2, "last_updated": "2021-01-02T08:00:00Z", "timestamp": "2021-01-01T08:00:00Z", - "ingress_interface": 2, "usages": [ "up_registration", "down_registration" diff --git a/control/mgmtapi/testdata/TestAPI_beacons b/control/mgmtapi/testdata/TestAPI_beacons index c04430a99..ef36d2859 100644 --- a/control/mgmtapi/testdata/TestAPI_beacons +++ b/control/mgmtapi/testdata/TestAPI_beacons @@ -17,9 +17,9 @@ } ], "id": "6e1f2ac35d1382a6064600007f9f270f6506c0b3453ee50423b5f1a73de53345", + "ingress_interface": 2, "last_updated": "2021-01-02T08:00:00Z", "timestamp": "2021-01-01T08:00:00Z", - "ingress_interface": 2, "usages": [ "up_registration", "down_registration" @@ -42,9 +42,9 @@ } ], "id": "ab23d63e6292412fe1c6afc778cd49ee4f758eef5e79cb9ed06864b0ee1e10b9", + "ingress_interface": 1, "last_updated": "2021-02-02T08:00:00Z", "timestamp": "2021-02-01T08:00:00Z", - "ingress_interface": 1, "usages": [ "core_registration" ] diff --git a/control/mgmtapi/testdata/TestAPI_beacons_descending_order b/control/mgmtapi/testdata/TestAPI_beacons_descending_order index ea2fe74d2..d09cdf60f 100644 --- a/control/mgmtapi/testdata/TestAPI_beacons_descending_order +++ b/control/mgmtapi/testdata/TestAPI_beacons_descending_order @@ -17,9 +17,9 @@ } ], "id": "ab23d63e6292412fe1c6afc778cd49ee4f758eef5e79cb9ed06864b0ee1e10b9", + "ingress_interface": 1, "last_updated": "2021-02-02T08:00:00Z", "timestamp": "2021-02-01T08:00:00Z", - "ingress_interface": 1, "usages": [ "core_registration" ] @@ -41,9 +41,9 @@ } ], "id": "6e1f2ac35d1382a6064600007f9f270f6506c0b3453ee50423b5f1a73de53345", + "ingress_interface": 2, "last_updated": "2021-01-02T08:00:00Z", "timestamp": "2021-01-01T08:00:00Z", - "ingress_interface": 2, "usages": [ "up_registration", "down_registration" diff --git a/control/mgmtapi/testdata/TestAPI_beacons_existing_usages b/control/mgmtapi/testdata/TestAPI_beacons_existing_usages index 0efe4dc5c..f32ef063b 100644 --- a/control/mgmtapi/testdata/TestAPI_beacons_existing_usages +++ b/control/mgmtapi/testdata/TestAPI_beacons_existing_usages @@ -17,9 +17,9 @@ } ], "id": "6e1f2ac35d1382a6064600007f9f270f6506c0b3453ee50423b5f1a73de53345", + "ingress_interface": 2, "last_updated": "2021-01-02T08:00:00Z", "timestamp": "2021-01-01T08:00:00Z", - "ingress_interface": 2, "usages": [ "up_registration", "down_registration" diff --git a/control/mgmtapi/testdata/TestAPI_beacons_sort_by_ingress_interface b/control/mgmtapi/testdata/TestAPI_beacons_sort_by_ingress_interface index ea2fe74d2..d09cdf60f 100644 --- a/control/mgmtapi/testdata/TestAPI_beacons_sort_by_ingress_interface +++ b/control/mgmtapi/testdata/TestAPI_beacons_sort_by_ingress_interface @@ -17,9 +17,9 @@ } ], "id": "ab23d63e6292412fe1c6afc778cd49ee4f758eef5e79cb9ed06864b0ee1e10b9", + "ingress_interface": 1, "last_updated": "2021-02-02T08:00:00Z", "timestamp": "2021-02-01T08:00:00Z", - "ingress_interface": 1, "usages": [ "core_registration" ] @@ -41,9 +41,9 @@ } ], "id": "6e1f2ac35d1382a6064600007f9f270f6506c0b3453ee50423b5f1a73de53345", + "ingress_interface": 2, "last_updated": "2021-01-02T08:00:00Z", "timestamp": "2021-01-01T08:00:00Z", - "ingress_interface": 2, "usages": [ "up_registration", "down_registration" diff --git a/control/mgmtapi/testdata/TestAPI_health_signer_degraded_trc_fails b/control/mgmtapi/testdata/TestAPI_health_signer_degraded_trc_fails index 5e4916c69..8a767360d 100644 --- a/control/mgmtapi/testdata/TestAPI_health_signer_degraded_trc_fails +++ b/control/mgmtapi/testdata/TestAPI_health_signer_degraded_trc_fails @@ -10,7 +10,7 @@ "status": "degraded" }, { - "data": {}, + "data": null, "name": "TRC for local ISD available", "status": "failing" }, diff --git a/control/mgmtapi/testdata/TestAPI_health_signer_error b/control/mgmtapi/testdata/TestAPI_health_signer_error index 85c76a488..f5ea656bc 100644 --- a/control/mgmtapi/testdata/TestAPI_health_signer_error +++ b/control/mgmtapi/testdata/TestAPI_health_signer_error @@ -2,12 +2,12 @@ "health": { "checks": [ { - "data": {}, + "data": null, "name": "valid signer available", "status": "failing" }, { - "data": {}, + "data": null, "name": "TRC for local ISD available", "status": "failing" }, diff --git a/control/mgmtapi/testdata/TestAPI_health_signer_fails b/control/mgmtapi/testdata/TestAPI_health_signer_fails index 203cf184e..8b1b747bf 100644 --- a/control/mgmtapi/testdata/TestAPI_health_signer_fails +++ b/control/mgmtapi/testdata/TestAPI_health_signer_fails @@ -2,7 +2,7 @@ "health": { "checks": [ { - "data": {}, + "data": null, "name": "valid signer available", "status": "failing" }, diff --git a/control/mgmtapi/testdata/TestAPI_health_signer_fails_trc_fails b/control/mgmtapi/testdata/TestAPI_health_signer_fails_trc_fails index 85c76a488..f5ea656bc 100644 --- a/control/mgmtapi/testdata/TestAPI_health_signer_fails_trc_fails +++ b/control/mgmtapi/testdata/TestAPI_health_signer_fails_trc_fails @@ -2,12 +2,12 @@ "health": { "checks": [ { - "data": {}, + "data": null, "name": "valid signer available", "status": "failing" }, { - "data": {}, + "data": null, "name": "TRC for local ISD available", "status": "failing" }, diff --git a/control/mgmtapi/testdata/TestAPI_health_signer_grace_period_trc_fails b/control/mgmtapi/testdata/TestAPI_health_signer_grace_period_trc_fails index d50913883..ac1d78572 100644 --- a/control/mgmtapi/testdata/TestAPI_health_signer_grace_period_trc_fails +++ b/control/mgmtapi/testdata/TestAPI_health_signer_grace_period_trc_fails @@ -11,7 +11,7 @@ "status": "degraded" }, { - "data": {}, + "data": null, "name": "TRC for local ISD available", "status": "failing" }, diff --git a/control/mgmtapi/testdata/TestAPI_health_trc_error b/control/mgmtapi/testdata/TestAPI_health_trc_error index eeddf2c74..ab07e5316 100644 --- a/control/mgmtapi/testdata/TestAPI_health_trc_error +++ b/control/mgmtapi/testdata/TestAPI_health_trc_error @@ -9,7 +9,7 @@ "status": "passing" }, { - "data": {}, + "data": null, "detail": "internal", "name": "TRC for local ISD available", "status": "failing" diff --git a/control/mgmtapi/testdata/TestAPI_health_trc_fails b/control/mgmtapi/testdata/TestAPI_health_trc_fails index 52bf0d8e3..3903fce61 100644 --- a/control/mgmtapi/testdata/TestAPI_health_trc_fails +++ b/control/mgmtapi/testdata/TestAPI_health_trc_fails @@ -9,7 +9,7 @@ "status": "passing" }, { - "data": {}, + "data": null, "name": "TRC for local ISD available", "status": "failing" }, diff --git a/control/mgmtapi/types.gen.go b/control/mgmtapi/types.gen.go index 8b35e1541..d6537cad2 100644 --- a/control/mgmtapi/types.gen.go +++ b/control/mgmtapi/types.gen.go @@ -4,47 +4,50 @@ package mgmtapi import ( - "encoding/json" - "fmt" "time" ) // Defines values for BeaconUsage. const ( - BeaconUsageCoreRegistration BeaconUsage = "core_registration" - - BeaconUsageDownRegistration BeaconUsage = "down_registration" - - BeaconUsagePropagation BeaconUsage = "propagation" - - BeaconUsageUpRegistration BeaconUsage = "up_registration" + CoreRegistration BeaconUsage = "core_registration" + DownRegistration BeaconUsage = "down_registration" + Propagation BeaconUsage = "propagation" + UpRegistration BeaconUsage = "up_registration" ) // Defines values for LogLevelLevel. const ( - LogLevelLevelDebug LogLevelLevel = "debug" - - LogLevelLevelError LogLevelLevel = "error" - - LogLevelLevelInfo LogLevelLevel = "info" + Debug LogLevelLevel = "debug" + Error LogLevelLevel = "error" + Info LogLevelLevel = "info" ) // Defines values for Status. const ( - StatusDegraded Status = "degraded" - - StatusFailing Status = "failing" + Degraded Status = "degraded" + Failing Status = "failing" + Passing Status = "passing" +) - StatusPassing Status = "passing" +// Defines values for GetBeaconsParamsSort. +const ( + Expiration GetBeaconsParamsSort = "expiration" + IngressInterface GetBeaconsParamsSort = "ingress_interface" + LastUpdated GetBeaconsParamsSort = "last_updated" + StartIsdAs GetBeaconsParamsSort = "start_isd_as" + Timestamp GetBeaconsParamsSort = "timestamp" ) // Beacon defines model for Beacon. type Beacon struct { - // Embedded struct due to allOf(#/components/schemas/Segment) - Segment `yaml:",inline"` - // Embedded fields due to inline allOf schema - // Ingress interface of the beacon. + Expiration time.Time `json:"expiration"` + Hops []Hop `json:"hops"` + Id SegmentID `json:"id"` + + // IngressInterface Ingress interface of the beacon. IngressInterface int `json:"ingress_interface"` + LastUpdated time.Time `json:"last_updated"` + Timestamp time.Time `json:"timestamp"` Usages BeaconUsages `json:"usages"` } @@ -57,7 +60,7 @@ type BeaconGetResponseJson struct { type BeaconUsage string // BeaconUsages defines model for BeaconUsages. -type BeaconUsages []BeaconUsage +type BeaconUsages = []BeaconUsage // CA defines model for CA. type CA struct { @@ -91,31 +94,29 @@ type ChainBrief struct { } // ChainID defines model for ChainID. -type ChainID string +type ChainID = string // Check defines model for Check. type Check struct { Data CheckData `json:"data"` - // Additional information. + // Detail Additional information. Detail *string `json:"detail,omitempty"` - // Name of health check. + // Name Name of health check. Name string `json:"name"` - // Reason for check failure. + // Reason Reason for check failure. Reason *string `json:"reason,omitempty"` Status Status `json:"status"` } // CheckData defines model for CheckData. -type CheckData struct { - AdditionalProperties map[string]interface{} `json:"-"` -} +type CheckData map[string]interface{} // Health defines model for Health. type Health struct { - // List of health checks. + // Checks List of health checks. Checks []Check `json:"checks"` Status Status `json:"status"` } @@ -132,15 +133,15 @@ type Hop struct { } // IsdAs defines model for IsdAs. -type IsdAs string +type IsdAs = string // LogLevel defines model for LogLevel. type LogLevel struct { - // Logging level + // Level Logging level Level LogLevelLevel `json:"level"` } -// Logging level +// LogLevelLevel Logging level type LogLevelLevel string // Policy defines model for Policy. @@ -150,19 +151,19 @@ type Policy struct { // Problem defines model for Problem. type Problem struct { - // A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Detail A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Detail *string `json:"detail,omitempty"` - // A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. + // Instance A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. Instance *string `json:"instance,omitempty"` - // The HTTP status code generated by the origin server for this occurrence of the problem. + // Status The HTTP status code generated by the origin server for this occurrence of the problem. Status int `json:"status"` - // A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Title A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Title string `json:"title"` - // A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. + // Type A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. Type *string `json:"type,omitempty"` } @@ -180,30 +181,30 @@ type SegmentBrief struct { EndIsdAs IsdAs `json:"end_isd_as"` Id SegmentID `json:"id"` - // Length of the segment. + // Length Length of the segment. Length int `json:"length"` StartIsdAs IsdAs `json:"start_isd_as"` } // SegmentID defines model for SegmentID. -type SegmentID string +type SegmentID = string // Signer defines model for Signer. type Signer struct { AsCertificate Certificate `json:"as_certificate"` - // Signer expiration imposed by chain and TRC validity. + // Expiration Signer expiration imposed by chain and TRC validity. Expiration time.Time `json:"expiration"` TrcId TRCID `json:"trc_id"` - // TRC used as trust root is in grace period, and the latest TRC cannot + // TrcInGracePeriod TRC used as trust root is in grace period, and the latest TRC cannot // be used as trust root. TrcInGracePeriod bool `json:"trc_in_grace_period"` } // StandardError defines model for StandardError. type StandardError struct { - // Error message + // Error Error message Error string `json:"error"` } @@ -216,7 +217,7 @@ type Subject struct { } // SubjectKeyID defines model for SubjectKeyID. -type SubjectKeyID string +type SubjectKeyID = string // TRC defines model for TRC. type TRC struct { @@ -240,9 +241,7 @@ type TRCID struct { } // Topology defines model for Topology. -type Topology struct { - AdditionalProperties map[string]interface{} `json:"-"` -} +type Topology map[string]interface{} // Validity defines model for Validity. type Validity struct { @@ -251,30 +250,30 @@ type Validity struct { } // BadRequest defines model for BadRequest. -type BadRequest StandardError +type BadRequest = StandardError // GetBeaconsParams defines parameters for GetBeacons. type GetBeaconsParams struct { - // Start ISD-AS of beacons. The address can include wildcards (0) both for the ISD and AS identifier. - StartIsdAs *IsdAs `json:"start_isd_as,omitempty"` + // StartIsdAs Start ISD-AS of beacons. The address can include wildcards (0) both for the ISD and AS identifier. + StartIsdAs *IsdAs `form:"start_isd_as,omitempty" json:"start_isd_as,omitempty"` - // Minimum allowed usages of the returned beacons. Only beacons that are allowed in all the usages in the list will be returned. - Usages *BeaconUsages `json:"usages,omitempty"` + // Usages Minimum allowed usages of the returned beacons. Only beacons that are allowed in all the usages in the list will be returned. + Usages *BeaconUsages `form:"usages,omitempty" json:"usages,omitempty"` - // Ingress interface id. - IngressInterface *int `json:"ingress_interface,omitempty"` + // IngressInterface Ingress interface id. + IngressInterface *int `form:"ingress_interface,omitempty" json:"ingress_interface,omitempty"` - // Timestamp at which returned beacons are valid. If unset then the current datetime is used. This only has an effect if `all=false`. - ValidAt *time.Time `json:"valid_at,omitempty"` + // ValidAt Timestamp at which returned beacons are valid. If unset then the current datetime is used. This only has an effect if `all=false`. + ValidAt *time.Time `form:"valid_at,omitempty" json:"valid_at,omitempty"` - // Include beacons regardless of expiration and creation time. - All *bool `json:"all,omitempty"` + // All Include beacons regardless of expiration and creation time. + All *bool `form:"all,omitempty" json:"all,omitempty"` - // Whether to reverse the sort order (ascending by default). - Desc *bool `json:"desc,omitempty"` + // Desc Whether to reverse the sort order (ascending by default). + Desc *bool `form:"desc,omitempty" json:"desc,omitempty"` - // Attribute by which results are sorted. The value `start_isd_as` refers to the ISD-AS identifier of the first hop. - Sort *GetBeaconsParamsSort `json:"sort,omitempty"` + // Sort Attribute by which results are sorted. The value `start_isd_as` refers to the ISD-AS identifier of the first hop. + Sort *GetBeaconsParamsSort `form:"sort,omitempty" json:"sort,omitempty"` } // GetBeaconsParamsSort defines parameters for GetBeacons. @@ -282,134 +281,25 @@ type GetBeaconsParamsSort string // GetCertificatesParams defines parameters for GetCertificates. type GetCertificatesParams struct { - IsdAs *IsdAs `json:"isd_as,omitempty"` - ValidAt *time.Time `json:"valid_at,omitempty"` - All *bool `json:"all,omitempty"` + IsdAs *IsdAs `form:"isd_as,omitempty" json:"isd_as,omitempty"` + ValidAt *time.Time `form:"valid_at,omitempty" json:"valid_at,omitempty"` + All *bool `form:"all,omitempty" json:"all,omitempty"` } -// SetLogLevelJSONBody defines parameters for SetLogLevel. -type SetLogLevelJSONBody LogLevel - // GetSegmentsParams defines parameters for GetSegments. type GetSegmentsParams struct { - // Start ISD-AS of segment. - StartIsdAs *IsdAs `json:"start_isd_as,omitempty"` + // StartIsdAs Start ISD-AS of segment. + StartIsdAs *IsdAs `form:"start_isd_as,omitempty" json:"start_isd_as,omitempty"` - // Terminal AS of segment. - EndIsdAs *IsdAs `json:"end_isd_as,omitempty"` + // EndIsdAs Terminal AS of segment. + EndIsdAs *IsdAs `form:"end_isd_as,omitempty" json:"end_isd_as,omitempty"` } // GetTrcsParams defines parameters for GetTrcs. type GetTrcsParams struct { - Isd *[]int `json:"isd,omitempty"` - All *bool `json:"all,omitempty"` + Isd *[]int `form:"isd,omitempty" json:"isd,omitempty"` + All *bool `form:"all,omitempty" json:"all,omitempty"` } // SetLogLevelJSONRequestBody defines body for SetLogLevel for application/json ContentType. -type SetLogLevelJSONRequestBody SetLogLevelJSONBody - -// Getter for additional properties for CheckData. Returns the specified -// element and whether it was found -func (a CheckData) Get(fieldName string) (value interface{}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for CheckData -func (a *CheckData) Set(fieldName string, value interface{}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]interface{}) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for CheckData to handle AdditionalProperties -func (a *CheckData) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { - var fieldVal interface{} - err := json.Unmarshal(fieldBuf, &fieldVal) - if err != nil { - return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) - } - a.AdditionalProperties[fieldName] = fieldVal - } - } - return nil -} - -// Override default JSON handling for CheckData to handle AdditionalProperties -func (a CheckData) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - for fieldName, field := range a.AdditionalProperties { - object[fieldName], err = json.Marshal(field) - if err != nil { - return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) - } - } - return json.Marshal(object) -} - -// Getter for additional properties for Topology. Returns the specified -// element and whether it was found -func (a Topology) Get(fieldName string) (value interface{}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for Topology -func (a *Topology) Set(fieldName string, value interface{}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]interface{}) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for Topology to handle AdditionalProperties -func (a *Topology) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { - var fieldVal interface{} - err := json.Unmarshal(fieldBuf, &fieldVal) - if err != nil { - return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) - } - a.AdditionalProperties[fieldName] = fieldVal - } - } - return nil -} - -// Override default JSON handling for Topology to handle AdditionalProperties -func (a Topology) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - for fieldName, field := range a.AdditionalProperties { - object[fieldName], err = json.Marshal(field) - if err != nil { - return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) - } - } - return json.Marshal(object) -} +type SetLogLevelJSONRequestBody = LogLevel diff --git a/daemon/mgmtapi/api.go b/daemon/mgmtapi/api.go index 754132352..60b867271 100644 --- a/daemon/mgmtapi/api.go +++ b/daemon/mgmtapi/api.go @@ -58,18 +58,18 @@ func (s *Server) GetSegments( ) { p := segapi.GetSegmentsParams{ - StartIsdAs: (*segapi.IsdAs)(params.StartIsdAs), - EndIsdAs: (*segapi.IsdAs)(params.EndIsdAs), + StartIsdAs: params.StartIsdAs, + EndIsdAs: params.EndIsdAs, } s.SegmentsServer.GetSegments(w, r, p) } func (s *Server) GetSegment(w http.ResponseWriter, r *http.Request, id SegmentID) { - s.SegmentsServer.GetSegment(w, r, segapi.SegmentID(id)) + s.SegmentsServer.GetSegment(w, r, id) } func (s *Server) GetSegmentBlob(w http.ResponseWriter, r *http.Request, id SegmentID) { - s.SegmentsServer.GetSegmentBlob(w, r, segapi.SegmentID(id)) + s.SegmentsServer.GetSegmentBlob(w, r, id) } // GetCertificates lists the certificate chains. @@ -80,7 +80,7 @@ func (s *Server) GetCertificates( ) { cppkiParams := cppkiapi.GetCertificatesParams{ - IsdAs: (*cppkiapi.IsdAs)(params.IsdAs), + IsdAs: params.IsdAs, ValidAt: params.ValidAt, All: params.All, } @@ -89,12 +89,12 @@ func (s *Server) GetCertificates( // GetCertificate lists the certificate chain for a given ChainID. func (s *Server) GetCertificate(w http.ResponseWriter, r *http.Request, chainID ChainID) { - s.CPPKIServer.GetCertificate(w, r, cppkiapi.ChainID(chainID)) + s.CPPKIServer.GetCertificate(w, r, chainID) } // GetCertificateBlob gnerates a certificate chain blob response encoded as PEM for a given chainId. func (s *Server) GetCertificateBlob(w http.ResponseWriter, r *http.Request, chainID ChainID) { - s.CPPKIServer.GetCertificateBlob(w, r, cppkiapi.ChainID(chainID)) + s.CPPKIServer.GetCertificateBlob(w, r, chainID) } // GetTrcs gets the trcs specified by it's params. diff --git a/daemon/mgmtapi/client.gen.go b/daemon/mgmtapi/client.gen.go index a27da2ba4..b6d34cf5e 100644 --- a/daemon/mgmtapi/client.gen.go +++ b/daemon/mgmtapi/client.gen.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -947,6 +946,7 @@ type GetCertificatesResponse struct { Body []byte HTTPResponse *http.Response JSON200 *[]ChainBrief + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -969,6 +969,7 @@ type GetCertificateResponse struct { Body []byte HTTPResponse *http.Response JSON200 *Chain + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -990,6 +991,7 @@ func (r GetCertificateResponse) StatusCode() int { type GetCertificateBlobResponse struct { Body []byte HTTPResponse *http.Response + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -1102,6 +1104,7 @@ type GetSegmentsResponse struct { Body []byte HTTPResponse *http.Response JSON200 *[]SegmentBrief + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -1124,6 +1127,7 @@ type GetSegmentResponse struct { Body []byte HTTPResponse *http.Response JSON200 *Segment + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -1145,6 +1149,7 @@ func (r GetSegmentResponse) StatusCode() int { type GetSegmentBlobResponse struct { Body []byte HTTPResponse *http.Response + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -1358,7 +1363,7 @@ func (c *ClientWithResponses) GetTrcBlobWithResponse(ctx context.Context, isd in // ParseGetCertificatesResponse parses an HTTP response from a GetCertificatesWithResponse call func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1377,6 +1382,13 @@ func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -1384,7 +1396,7 @@ func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, // ParseGetCertificateResponse parses an HTTP response from a GetCertificateWithResponse call func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1403,6 +1415,13 @@ func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, e } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -1410,7 +1429,7 @@ func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, e // ParseGetCertificateBlobResponse parses an HTTP response from a GetCertificateBlobWithResponse call func ParseGetCertificateBlobResponse(rsp *http.Response) (*GetCertificateBlobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1421,12 +1440,22 @@ func ParseGetCertificateBlobResponse(rsp *http.Response) (*GetCertificateBlobRes HTTPResponse: rsp, } + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + return response, nil } // ParseGetConfigResponse parses an HTTP response from a GetConfigWithResponse call func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1452,7 +1481,7 @@ func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { // ParseGetInfoResponse parses an HTTP response from a GetInfoWithResponse call func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1478,7 +1507,7 @@ func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { // ParseGetLogLevelResponse parses an HTTP response from a GetLogLevelWithResponse call func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1511,7 +1540,7 @@ func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) // ParseSetLogLevelResponse parses an HTTP response from a SetLogLevelWithResponse call func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1544,7 +1573,7 @@ func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) // ParseGetSegmentsResponse parses an HTTP response from a GetSegmentsWithResponse call func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1563,6 +1592,13 @@ func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -1570,7 +1606,7 @@ func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) // ParseGetSegmentResponse parses an HTTP response from a GetSegmentWithResponse call func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1589,6 +1625,13 @@ func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -1596,7 +1639,7 @@ func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { // ParseGetSegmentBlobResponse parses an HTTP response from a GetSegmentBlobWithResponse call func ParseGetSegmentBlobResponse(rsp *http.Response) (*GetSegmentBlobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1607,12 +1650,22 @@ func ParseGetSegmentBlobResponse(rsp *http.Response) (*GetSegmentBlobResponse, e HTTPResponse: rsp, } + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + return response, nil } // ParseGetTrcsResponse parses an HTTP response from a GetTrcsWithResponse call func ParseGetTrcsResponse(rsp *http.Response) (*GetTrcsResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1645,7 +1698,7 @@ func ParseGetTrcsResponse(rsp *http.Response) (*GetTrcsResponse, error) { // ParseGetTrcResponse parses an HTTP response from a GetTrcWithResponse call func ParseGetTrcResponse(rsp *http.Response) (*GetTrcResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -1678,7 +1731,7 @@ func ParseGetTrcResponse(rsp *http.Response) (*GetTrcResponse, error) { // ParseGetTrcBlobResponse parses an HTTP response from a GetTrcBlobWithResponse call func ParseGetTrcBlobResponse(rsp *http.Response) (*GetTrcBlobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err diff --git a/daemon/mgmtapi/server.gen.go b/daemon/mgmtapi/server.gen.go index 385b52461..d7562b91b 100644 --- a/daemon/mgmtapi/server.gen.go +++ b/daemon/mgmtapi/server.gen.go @@ -61,7 +61,7 @@ type ServerInterfaceWrapper struct { ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) } -type MiddlewareFunc func(http.HandlerFunc) http.HandlerFunc +type MiddlewareFunc func(http.Handler) http.Handler // GetCertificates operation middleware func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *http.Request) { @@ -73,9 +73,6 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt var params GetCertificatesParams // ------------- Optional query parameter "isd_as" ------------- - if paramValue := r.URL.Query().Get("isd_as"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "isd_as", r.URL.Query(), ¶ms.IsdAs) if err != nil { @@ -84,9 +81,6 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt } // ------------- Optional query parameter "valid_at" ------------- - if paramValue := r.URL.Query().Get("valid_at"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "valid_at", r.URL.Query(), ¶ms.ValidAt) if err != nil { @@ -95,9 +89,6 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt } // ------------- Optional query parameter "all" ------------- - if paramValue := r.URL.Query().Get("all"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "all", r.URL.Query(), ¶ms.All) if err != nil { @@ -105,15 +96,15 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificates(w, r, params) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetCertificate operation middleware @@ -125,21 +116,21 @@ func (siw *ServerInterfaceWrapper) GetCertificate(w http.ResponseWriter, r *http // ------------- Path parameter "chain-id" ------------- var chainId ChainID - err = runtime.BindStyledParameter("simple", false, "chain-id", chi.URLParam(r, "chain-id"), &chainId) + err = runtime.BindStyledParameterWithLocation("simple", false, "chain-id", runtime.ParamLocationPath, chi.URLParam(r, "chain-id"), &chainId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "chain-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificate(w, r, chainId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetCertificateBlob operation middleware @@ -151,81 +142,81 @@ func (siw *ServerInterfaceWrapper) GetCertificateBlob(w http.ResponseWriter, r * // ------------- Path parameter "chain-id" ------------- var chainId ChainID - err = runtime.BindStyledParameter("simple", false, "chain-id", chi.URLParam(r, "chain-id"), &chainId) + err = runtime.BindStyledParameterWithLocation("simple", false, "chain-id", runtime.ParamLocationPath, chi.URLParam(r, "chain-id"), &chainId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "chain-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificateBlob(w, r, chainId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetConfig operation middleware func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetConfig(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetInfo operation middleware func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInfo(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetLogLevel operation middleware func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetLogLevel(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // SetLogLevel operation middleware func (siw *ServerInterfaceWrapper) SetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetLogLevel(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetSegments operation middleware @@ -238,9 +229,6 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re var params GetSegmentsParams // ------------- Optional query parameter "start_isd_as" ------------- - if paramValue := r.URL.Query().Get("start_isd_as"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "start_isd_as", r.URL.Query(), ¶ms.StartIsdAs) if err != nil { @@ -249,9 +237,6 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re } // ------------- Optional query parameter "end_isd_as" ------------- - if paramValue := r.URL.Query().Get("end_isd_as"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "end_isd_as", r.URL.Query(), ¶ms.EndIsdAs) if err != nil { @@ -259,15 +244,15 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegments(w, r, params) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetSegment operation middleware @@ -279,21 +264,21 @@ func (siw *ServerInterfaceWrapper) GetSegment(w http.ResponseWriter, r *http.Req // ------------- Path parameter "segment-id" ------------- var segmentId SegmentID - err = runtime.BindStyledParameter("simple", false, "segment-id", chi.URLParam(r, "segment-id"), &segmentId) + err = runtime.BindStyledParameterWithLocation("simple", false, "segment-id", runtime.ParamLocationPath, chi.URLParam(r, "segment-id"), &segmentId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "segment-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegment(w, r, segmentId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetSegmentBlob operation middleware @@ -305,21 +290,21 @@ func (siw *ServerInterfaceWrapper) GetSegmentBlob(w http.ResponseWriter, r *http // ------------- Path parameter "segment-id" ------------- var segmentId SegmentID - err = runtime.BindStyledParameter("simple", false, "segment-id", chi.URLParam(r, "segment-id"), &segmentId) + err = runtime.BindStyledParameterWithLocation("simple", false, "segment-id", runtime.ParamLocationPath, chi.URLParam(r, "segment-id"), &segmentId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "segment-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegmentBlob(w, r, segmentId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetTrcs operation middleware @@ -332,9 +317,6 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques var params GetTrcsParams // ------------- Optional query parameter "isd" ------------- - if paramValue := r.URL.Query().Get("isd"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", false, false, "isd", r.URL.Query(), ¶ms.Isd) if err != nil { @@ -343,9 +325,6 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques } // ------------- Optional query parameter "all" ------------- - if paramValue := r.URL.Query().Get("all"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "all", r.URL.Query(), ¶ms.All) if err != nil { @@ -353,15 +332,15 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcs(w, r, params) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetTrc operation middleware @@ -373,7 +352,7 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request // ------------- Path parameter "isd" ------------- var isd int - err = runtime.BindStyledParameter("simple", false, "isd", chi.URLParam(r, "isd"), &isd) + err = runtime.BindStyledParameterWithLocation("simple", false, "isd", runtime.ParamLocationPath, chi.URLParam(r, "isd"), &isd) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "isd", Err: err}) return @@ -382,7 +361,7 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request // ------------- Path parameter "base" ------------- var base int - err = runtime.BindStyledParameter("simple", false, "base", chi.URLParam(r, "base"), &base) + err = runtime.BindStyledParameterWithLocation("simple", false, "base", runtime.ParamLocationPath, chi.URLParam(r, "base"), &base) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "base", Err: err}) return @@ -391,21 +370,21 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request // ------------- Path parameter "serial" ------------- var serial int - err = runtime.BindStyledParameter("simple", false, "serial", chi.URLParam(r, "serial"), &serial) + err = runtime.BindStyledParameterWithLocation("simple", false, "serial", runtime.ParamLocationPath, chi.URLParam(r, "serial"), &serial) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "serial", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrc(w, r, isd, base, serial) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetTrcBlob operation middleware @@ -417,7 +396,7 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req // ------------- Path parameter "isd" ------------- var isd int - err = runtime.BindStyledParameter("simple", false, "isd", chi.URLParam(r, "isd"), &isd) + err = runtime.BindStyledParameterWithLocation("simple", false, "isd", runtime.ParamLocationPath, chi.URLParam(r, "isd"), &isd) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "isd", Err: err}) return @@ -426,7 +405,7 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req // ------------- Path parameter "base" ------------- var base int - err = runtime.BindStyledParameter("simple", false, "base", chi.URLParam(r, "base"), &base) + err = runtime.BindStyledParameterWithLocation("simple", false, "base", runtime.ParamLocationPath, chi.URLParam(r, "base"), &base) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "base", Err: err}) return @@ -435,21 +414,21 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req // ------------- Path parameter "serial" ------------- var serial int - err = runtime.BindStyledParameter("simple", false, "serial", chi.URLParam(r, "serial"), &serial) + err = runtime.BindStyledParameterWithLocation("simple", false, "serial", runtime.ParamLocationPath, chi.URLParam(r, "serial"), &serial) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "serial", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcBlob(w, r, isd, base, serial) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } type UnescapedCookieParamError struct { @@ -465,16 +444,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshalingParamError struct { +type UnmarshallingParamError struct { ParamName string Err error } -func (e *UnmarshalingParamError) Error() string { - return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshallingParamError) Error() string { + return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshalingParamError) Unwrap() error { +func (e *UnmarshallingParamError) Unwrap() error { return e.Err } diff --git a/daemon/mgmtapi/types.gen.go b/daemon/mgmtapi/types.gen.go index 6e6b51004..ce27a9447 100644 --- a/daemon/mgmtapi/types.gen.go +++ b/daemon/mgmtapi/types.gen.go @@ -9,11 +9,9 @@ import ( // Defines values for LogLevelLevel. const ( - LogLevelLevelDebug LogLevelLevel = "debug" - - LogLevelLevelError LogLevelLevel = "error" - - LogLevelLevelInfo LogLevelLevel = "info" + Debug LogLevelLevel = "debug" + Error LogLevelLevel = "error" + Info LogLevelLevel = "info" ) // Certificate defines model for Certificate. @@ -40,7 +38,7 @@ type ChainBrief struct { } // ChainID defines model for ChainID. -type ChainID string +type ChainID = string // Hop defines model for Hop. type Hop struct { @@ -49,32 +47,32 @@ type Hop struct { } // IsdAs defines model for IsdAs. -type IsdAs string +type IsdAs = string // LogLevel defines model for LogLevel. type LogLevel struct { - // Logging level + // Level Logging level Level LogLevelLevel `json:"level"` } -// Logging level +// LogLevelLevel Logging level type LogLevelLevel string // Problem defines model for Problem. type Problem struct { - // A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Detail A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Detail *string `json:"detail,omitempty"` - // A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. + // Instance A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. Instance *string `json:"instance,omitempty"` - // The HTTP status code generated by the origin server for this occurrence of the problem. + // Status The HTTP status code generated by the origin server for this occurrence of the problem. Status int `json:"status"` - // A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Title A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Title string `json:"title"` - // A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. + // Type A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. Type *string `json:"type,omitempty"` } @@ -92,22 +90,22 @@ type SegmentBrief struct { EndIsdAs IsdAs `json:"end_isd_as"` Id SegmentID `json:"id"` - // Length of the segment. + // Length Length of the segment. Length int `json:"length"` StartIsdAs IsdAs `json:"start_isd_as"` } // SegmentID defines model for SegmentID. -type SegmentID string +type SegmentID = string // StandardError defines model for StandardError. type StandardError struct { - // Error message + // Error Error message Error string `json:"error"` } // SubjectKeyID defines model for SubjectKeyID. -type SubjectKeyID string +type SubjectKeyID = string // TRC defines model for TRC. type TRC struct { @@ -137,32 +135,29 @@ type Validity struct { } // BadRequest defines model for BadRequest. -type BadRequest StandardError +type BadRequest = StandardError // GetCertificatesParams defines parameters for GetCertificates. type GetCertificatesParams struct { - IsdAs *IsdAs `json:"isd_as,omitempty"` - ValidAt *time.Time `json:"valid_at,omitempty"` - All *bool `json:"all,omitempty"` + IsdAs *IsdAs `form:"isd_as,omitempty" json:"isd_as,omitempty"` + ValidAt *time.Time `form:"valid_at,omitempty" json:"valid_at,omitempty"` + All *bool `form:"all,omitempty" json:"all,omitempty"` } -// SetLogLevelJSONBody defines parameters for SetLogLevel. -type SetLogLevelJSONBody LogLevel - // GetSegmentsParams defines parameters for GetSegments. type GetSegmentsParams struct { - // Start ISD-AS of segment. - StartIsdAs *IsdAs `json:"start_isd_as,omitempty"` + // StartIsdAs Start ISD-AS of segment. + StartIsdAs *IsdAs `form:"start_isd_as,omitempty" json:"start_isd_as,omitempty"` - // Terminal AS of segment. - EndIsdAs *IsdAs `json:"end_isd_as,omitempty"` + // EndIsdAs Terminal AS of segment. + EndIsdAs *IsdAs `form:"end_isd_as,omitempty" json:"end_isd_as,omitempty"` } // GetTrcsParams defines parameters for GetTrcs. type GetTrcsParams struct { - Isd *[]int `json:"isd,omitempty"` - All *bool `json:"all,omitempty"` + Isd *[]int `form:"isd,omitempty" json:"isd,omitempty"` + All *bool `form:"all,omitempty" json:"all,omitempty"` } // SetLogLevelJSONRequestBody defines body for SetLogLevel for application/json ContentType. -type SetLogLevelJSONRequestBody SetLogLevelJSONBody +type SetLogLevelJSONRequestBody = LogLevel diff --git a/dispatcher/mgmtapi/client.gen.go b/dispatcher/mgmtapi/client.gen.go index 47d9eb80c..d87b18ca4 100644 --- a/dispatcher/mgmtapi/client.gen.go +++ b/dispatcher/mgmtapi/client.gen.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -478,7 +477,7 @@ func (c *ClientWithResponses) SetLogLevelWithResponse(ctx context.Context, body // ParseGetConfigResponse parses an HTTP response from a GetConfigWithResponse call func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -504,7 +503,7 @@ func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { // ParseGetInfoResponse parses an HTTP response from a GetInfoWithResponse call func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -530,7 +529,7 @@ func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { // ParseGetLogLevelResponse parses an HTTP response from a GetLogLevelWithResponse call func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -563,7 +562,7 @@ func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) // ParseSetLogLevelResponse parses an HTTP response from a SetLogLevelWithResponse call func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err diff --git a/dispatcher/mgmtapi/server.gen.go b/dispatcher/mgmtapi/server.gen.go index 7f11736b4..c6b1ffa8c 100644 --- a/dispatcher/mgmtapi/server.gen.go +++ b/dispatcher/mgmtapi/server.gen.go @@ -33,66 +33,66 @@ type ServerInterfaceWrapper struct { ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) } -type MiddlewareFunc func(http.HandlerFunc) http.HandlerFunc +type MiddlewareFunc func(http.Handler) http.Handler // GetConfig operation middleware func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetConfig(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetInfo operation middleware func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInfo(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetLogLevel operation middleware func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetLogLevel(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // SetLogLevel operation middleware func (siw *ServerInterfaceWrapper) SetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetLogLevel(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } type UnescapedCookieParamError struct { @@ -108,16 +108,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshalingParamError struct { +type UnmarshallingParamError struct { ParamName string Err error } -func (e *UnmarshalingParamError) Error() string { - return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshallingParamError) Error() string { + return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshalingParamError) Unwrap() error { +func (e *UnmarshallingParamError) Unwrap() error { return e.Err } diff --git a/dispatcher/mgmtapi/types.gen.go b/dispatcher/mgmtapi/types.gen.go index 1988bc315..2a16e0030 100644 --- a/dispatcher/mgmtapi/types.gen.go +++ b/dispatcher/mgmtapi/types.gen.go @@ -5,33 +5,28 @@ package mgmtapi // Defines values for LogLevelLevel. const ( - LogLevelLevelDebug LogLevelLevel = "debug" - - LogLevelLevelError LogLevelLevel = "error" - - LogLevelLevelInfo LogLevelLevel = "info" + Debug LogLevelLevel = "debug" + Error LogLevelLevel = "error" + Info LogLevelLevel = "info" ) // LogLevel defines model for LogLevel. type LogLevel struct { - // Logging level + // Level Logging level Level LogLevelLevel `json:"level"` } -// Logging level +// LogLevelLevel Logging level type LogLevelLevel string // StandardError defines model for StandardError. type StandardError struct { - // Error message + // Error Error message Error string `json:"error"` } // BadRequest defines model for BadRequest. -type BadRequest StandardError - -// SetLogLevelJSONBody defines parameters for SetLogLevel. -type SetLogLevelJSONBody LogLevel +type BadRequest = StandardError // SetLogLevelJSONRequestBody defines body for SetLogLevel for application/json ContentType. -type SetLogLevelJSONRequestBody SetLogLevelJSONBody +type SetLogLevelJSONRequestBody = LogLevel diff --git a/doc/build/dependencies.rst b/doc/build/dependencies.rst index a18fc3629..b29c01c00 100644 --- a/doc/build/dependencies.rst +++ b/doc/build/dependencies.rst @@ -22,7 +22,7 @@ Workflow to modify dependencies To add/remove or update dependencies: 1. Modify ``go.mod``, manually or using e.g. ``go get``. -2. ``go mod tidy`` +2. ``make go-mod-tidy`` 3. ``make go_deps.bzl`` 4. ``make licenses``, to update the licenses with the new dependency 5. ``make gazelle``, to update the build files that depend on the newly added dependency diff --git a/doc/command/scion-pki/scion-pki_completion_bash.rst b/doc/command/scion-pki/scion-pki_completion_bash.rst index b8eb1654c..6bbc48df6 100755 --- a/doc/command/scion-pki/scion-pki_completion_bash.rst +++ b/doc/command/scion-pki/scion-pki_completion_bash.rst @@ -28,7 +28,7 @@ To load completions for every new session, execute once: #### macOS: - scion-pki completion bash > /usr/local/etc/bash_completion.d/scion-pki + scion-pki completion bash > $(brew --prefix)/etc/bash_completion.d/scion-pki You will need to start a new shell for this setup to take effect. diff --git a/doc/command/scion-pki/scion-pki_completion_zsh.rst b/doc/command/scion-pki/scion-pki_completion_zsh.rst index be8c994f8..1a6000ab3 100755 --- a/doc/command/scion-pki/scion-pki_completion_zsh.rst +++ b/doc/command/scion-pki/scion-pki_completion_zsh.rst @@ -18,6 +18,10 @@ to enable it. You can execute the following once: echo "autoload -U compinit; compinit" >> ~/.zshrc +To load completions in your current shell session: + + source <(scion-pki completion zsh); compdef _scion-pki scion-pki + To load completions for every new session, execute once: #### Linux: @@ -26,7 +30,7 @@ To load completions for every new session, execute once: #### macOS: - scion-pki completion zsh > /usr/local/share/zsh/site-functions/_scion-pki + scion-pki completion zsh > $(brew --prefix)/share/zsh/site-functions/_scion-pki You will need to start a new shell for this setup to take effect. diff --git a/doc/command/scion/scion_completion_bash.rst b/doc/command/scion/scion_completion_bash.rst index beb0bf0ad..45d35c5ae 100755 --- a/doc/command/scion/scion_completion_bash.rst +++ b/doc/command/scion/scion_completion_bash.rst @@ -28,7 +28,7 @@ To load completions for every new session, execute once: #### macOS: - scion completion bash > /usr/local/etc/bash_completion.d/scion + scion completion bash > $(brew --prefix)/etc/bash_completion.d/scion You will need to start a new shell for this setup to take effect. diff --git a/doc/command/scion/scion_completion_zsh.rst b/doc/command/scion/scion_completion_zsh.rst index 8d176feed..e95c3725f 100755 --- a/doc/command/scion/scion_completion_zsh.rst +++ b/doc/command/scion/scion_completion_zsh.rst @@ -18,6 +18,10 @@ to enable it. You can execute the following once: echo "autoload -U compinit; compinit" >> ~/.zshrc +To load completions in your current shell session: + + source <(scion completion zsh); compdef _scion scion + To load completions for every new session, execute once: #### Linux: @@ -26,7 +30,7 @@ To load completions for every new session, execute once: #### macOS: - scion completion zsh > /usr/local/share/zsh/site-functions/_scion + scion completion zsh > $(brew --prefix)/share/zsh/site-functions/_scion You will need to start a new shell for this setup to take effect. diff --git a/gateway/mgmtapi/client.gen.go b/gateway/mgmtapi/client.gen.go index 47d9eb80c..d87b18ca4 100644 --- a/gateway/mgmtapi/client.gen.go +++ b/gateway/mgmtapi/client.gen.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -478,7 +477,7 @@ func (c *ClientWithResponses) SetLogLevelWithResponse(ctx context.Context, body // ParseGetConfigResponse parses an HTTP response from a GetConfigWithResponse call func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -504,7 +503,7 @@ func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { // ParseGetInfoResponse parses an HTTP response from a GetInfoWithResponse call func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -530,7 +529,7 @@ func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { // ParseGetLogLevelResponse parses an HTTP response from a GetLogLevelWithResponse call func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -563,7 +562,7 @@ func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) // ParseSetLogLevelResponse parses an HTTP response from a SetLogLevelWithResponse call func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err diff --git a/gateway/mgmtapi/server.gen.go b/gateway/mgmtapi/server.gen.go index 7f11736b4..c6b1ffa8c 100644 --- a/gateway/mgmtapi/server.gen.go +++ b/gateway/mgmtapi/server.gen.go @@ -33,66 +33,66 @@ type ServerInterfaceWrapper struct { ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) } -type MiddlewareFunc func(http.HandlerFunc) http.HandlerFunc +type MiddlewareFunc func(http.Handler) http.Handler // GetConfig operation middleware func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetConfig(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetInfo operation middleware func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInfo(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetLogLevel operation middleware func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetLogLevel(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // SetLogLevel operation middleware func (siw *ServerInterfaceWrapper) SetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetLogLevel(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } type UnescapedCookieParamError struct { @@ -108,16 +108,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshalingParamError struct { +type UnmarshallingParamError struct { ParamName string Err error } -func (e *UnmarshalingParamError) Error() string { - return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshallingParamError) Error() string { + return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshalingParamError) Unwrap() error { +func (e *UnmarshallingParamError) Unwrap() error { return e.Err } diff --git a/gateway/mgmtapi/types.gen.go b/gateway/mgmtapi/types.gen.go index 1988bc315..2a16e0030 100644 --- a/gateway/mgmtapi/types.gen.go +++ b/gateway/mgmtapi/types.gen.go @@ -5,33 +5,28 @@ package mgmtapi // Defines values for LogLevelLevel. const ( - LogLevelLevelDebug LogLevelLevel = "debug" - - LogLevelLevelError LogLevelLevel = "error" - - LogLevelLevelInfo LogLevelLevel = "info" + Debug LogLevelLevel = "debug" + Error LogLevelLevel = "error" + Info LogLevelLevel = "info" ) // LogLevel defines model for LogLevel. type LogLevel struct { - // Logging level + // Level Logging level Level LogLevelLevel `json:"level"` } -// Logging level +// LogLevelLevel Logging level type LogLevelLevel string // StandardError defines model for StandardError. type StandardError struct { - // Error message + // Error Error message Error string `json:"error"` } // BadRequest defines model for BadRequest. -type BadRequest StandardError - -// SetLogLevelJSONBody defines parameters for SetLogLevel. -type SetLogLevelJSONBody LogLevel +type BadRequest = StandardError // SetLogLevelJSONRequestBody defines body for SetLogLevel for application/json ContentType. -type SetLogLevelJSONRequestBody SetLogLevelJSONBody +type SetLogLevelJSONRequestBody = LogLevel diff --git a/go.mod b/go.mod index fc37aa9a8..ab01fd8f9 100644 --- a/go.mod +++ b/go.mod @@ -2,116 +2,119 @@ module github.com/scionproto/scion require ( github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220209173558-ad29539cd2e9 - github.com/bazelbuild/rules_go v0.29.0 - github.com/buildkite/go-buildkite/v2 v2.8.1 - github.com/dchest/cmac v0.0.0-20150527144652-62ff55a1048c - github.com/deepmap/oapi-codegen v1.9.0 - github.com/fatih/color v1.13.0 - github.com/getkin/kin-openapi v0.80.0 - github.com/go-chi/chi/v5 v5.0.2 - github.com/go-chi/cors v1.1.1 + github.com/bazelbuild/rules_go v0.38.1 + github.com/buildkite/go-buildkite/v2 v2.9.0 + github.com/dchest/cmac v1.0.0 + github.com/deepmap/oapi-codegen v1.12.5-0.20230221180206-2b52cd58cf5b + github.com/fatih/color v1.14.1 + github.com/getkin/kin-openapi v0.114.0 + github.com/go-chi/chi/v5 v5.0.8 + github.com/go-chi/cors v1.2.1 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.2 - github.com/google/go-cmp v0.5.8 - github.com/google/go-containerregistry v0.5.1 - github.com/google/gopacket v1.1.16-0.20190123011826-102d5ca2098c + github.com/google/go-cmp v0.5.9 + github.com/google/go-containerregistry v0.13.0 + github.com/google/gopacket v1.1.19 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 - github.com/hashicorp/golang-lru v0.5.4 + github.com/hashicorp/golang-lru v0.6.0 github.com/iancoleman/strcase v0.2.0 - github.com/lestrrat-go/jwx v1.2.7 + github.com/lestrrat-go/jwx v1.2.25 github.com/lucas-clemente/quic-go v0.29.1 - github.com/mattn/go-isatty v0.0.14 - github.com/mattn/go-sqlite3 v1.14.4 + github.com/mattn/go-isatty v0.0.17 + github.com/mattn/go-sqlite3 v1.14.16 github.com/olekukonko/tablewriter v0.0.5 github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.1-0.20180815053127-5633e0862627+incompatible - github.com/pelletier/go-toml v1.9.4 + github.com/pelletier/go-toml v1.9.5 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.11.1 - github.com/sergi/go-diff v1.2.0 - github.com/smartystreets/goconvey v1.6.7 - github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b - github.com/spf13/cobra v1.4.0 + github.com/prometheus/client_golang v1.14.0 + github.com/sergi/go-diff v1.3.1 + github.com/smartystreets/goconvey v1.7.2 + github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 + github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.10.0 - github.com/stretchr/testify v1.7.0 - github.com/uber/jaeger-client-go v2.29.1+incompatible - github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 - go.uber.org/goleak v1.1.10 - go.uber.org/zap v1.17.0 - golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 - golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/tools v0.1.10 - google.golang.org/grpc v1.42.0 - google.golang.org/grpc/examples v0.0.0-20210630181457-52546c5d89b7 - google.golang.org/protobuf v1.27.1 + github.com/spf13/viper v1.15.0 + github.com/stretchr/testify v1.8.1 + github.com/uber/jaeger-client-go v2.30.0+incompatible + github.com/vishvananda/netlink v1.2.1-beta.2 + go.uber.org/goleak v1.2.1 + go.uber.org/zap v1.24.0 + golang.org/x/crypto v0.6.0 + golang.org/x/net v0.7.0 + golang.org/x/sync v0.1.0 + golang.org/x/tools v0.6.0 + google.golang.org/grpc v1.53.0 + google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 + google.golang.org/protobuf v1.28.1 gopkg.in/yaml.v2 v2.4.0 inet.af/netaddr v0.0.0-20220811202034-502d2d690317 ) require ( + github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect + github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d // indirect - github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/ghodss/yaml v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/swag v0.19.14 // indirect + github.com/go-openapi/swag v0.21.1 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect - github.com/goccy/go-json v0.7.8 // indirect + github.com/goccy/go-json v0.9.11 // indirect github.com/google/go-querystring v1.0.1-0.20190318165438-c8c88dbee036 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/invopop/yaml v0.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jtolds/gls v4.20.0+incompatible // indirect github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect github.com/lestrrat-go/blackmagic v1.0.0 // indirect - github.com/lestrrat-go/httpcc v1.0.0 // indirect + github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/iter v1.0.1 // indirect github.com/lestrrat-go/option v1.0.0 // indirect - github.com/magiconair/properties v1.8.5 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 // indirect - github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/onsi/ginkgo v1.16.4 // indirect + github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/perimeterx/marshmallow v1.1.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/smartystreets/assertions v1.0.0 // indirect - github.com/spf13/afero v1.6.0 // indirect - github.com/spf13/cast v1.4.1 // indirect + github.com/smartystreets/assertions v1.2.0 // indirect + github.com/spf13/afero v1.9.3 // indirect + github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/subosito/gotenv v1.2.0 // indirect + github.com/subosito/gotenv v1.4.2 // indirect github.com/uber/jaeger-lib v2.0.0+incompatible // indirect github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.8.0 // indirect go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect - gopkg.in/ini.v1 v1.66.2 // indirect + golang.org/x/mod v0.8.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 3a2225e7e..c8e8da25e 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -13,6 +14,9 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -30,163 +34,114 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220209173558-ad29539cd2e9 h1:zvkJv+9Pxm1nnEMcKnShREt4qtduHKz4iw4AB4ul0Ao= github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220209173558-ad29539cd2e9/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/bazelbuild/rules_go v0.29.0 h1:SfxjyO/V68rVnzOHop92fB0gv/Aa75KNLAN0PMqXbIw= -github.com/bazelbuild/rules_go v0.29.0/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M= +github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/bazelbuild/rules_go v0.38.1 h1:YGNsLhWe18Ielebav7cClP3GMwBxBE+xEArLHtmXDx8= +github.com/bazelbuild/rules_go v0.38.1/go.mod h1:TMHmtfpvyfsxaqfL9WnahCsXMWDMICTw7XeK9yVb+YU= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/buildkite/go-buildkite/v2 v2.8.1 h1:aWsgMl3lA6xLSAyAhEO0DaHg7a7GVf/50mqVDC1Zt0A= -github.com/buildkite/go-buildkite/v2 v2.8.1/go.mod h1:kRCClqF2FuCFK42+Jk8ggYUMMAQXJC3uMjBt6W/ajJ0= +github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= +github.com/buildkite/go-buildkite/v2 v2.9.0 h1:K3eQZXm6ZFphKBIndOI+TnbluA8RDg5JMpwoFxSg3sc= +github.com/buildkite/go-buildkite/v2 v2.9.0/go.mod h1:kRCClqF2FuCFK42+Jk8ggYUMMAQXJC3uMjBt6W/ajJ0= github.com/cenkalti/backoff v1.1.1-0.20171020064038-309aa717adbf/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/stargz-snapshotter/estargz v0.4.1 h1:5e7heayhB7CcgdTkqfZqrNaNv15gABwr3Q2jBTbLlt4= -github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/containerd/stargz-snapshotter/estargz v0.12.1 h1:+7nYmHJb0tEkcRaAW+MHqoKaJYZmkikupxCqVtmPuY0= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dchest/cmac v0.0.0-20150527144652-62ff55a1048c h1:qoavXEzRRUfup81LsDQv4fnUQbLyorpPz6WxiwdiU7A= -github.com/dchest/cmac v0.0.0-20150527144652-62ff55a1048c/go.mod h1:vWqNmss2I/DL9JKC95Lkwp+lzw+v8hwsQs7hQKyQpwk= +github.com/dchest/cmac v1.0.0 h1:Vaorm9FVpO2P+YmRdH0RVCUB1XF3Ge1yg9scPvJphyk= +github.com/dchest/cmac v1.0.0/go.mod h1:0zViPqHm8iZwwMl1cuK3HqK7Tu4Q7DV4EuMIOUwBVQ0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d h1:1iy2qD6JEhHKKhUOA9IWs7mjco7lnw2qx8FsRI2wirE= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= -github.com/deepmap/oapi-codegen v1.9.0 h1:qpyRY+dzjMai5QejjA53ebnBtcSvIcZOtYwVlsgdxOc= -github.com/deepmap/oapi-codegen v1.9.0/go.mod h1:7t4DbSxmAffcTEgrWvsPYEE2aOARZ8ZKWp3hDuZkHNc= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017 h1:2HQmlpI3yI9deH18Q6xiSOIjXD4sLI55Y/gfpa8/558= -github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7 h1:Cvj7S8I4Xpx78KAl6TwTmMHuHlZ/0SM60NUneGJQ7IE= -github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= -github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/deepmap/oapi-codegen v1.12.5-0.20230221180206-2b52cd58cf5b h1:LDDxTtOtlGKTubzsuonFRmhMgP5zfWmM+G3Ql948TAs= +github.com/deepmap/oapi-codegen v1.12.5-0.20230221180206-2b52cd58cf5b/go.mod h1:Oq/fBIJxL5rD6wZen0I3a6yXCwh7Fl0i8d5e4kYYA8c= +github.com/docker/cli v20.10.20+incompatible h1:lWQbHSHUFs7KraSN2jOJK7zbMS2jNCHI4mt4xUFUVQ4= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/docker v20.10.20+incompatible h1:kH9tx6XO+359d+iAkumyKDc5Q1kOwPuAUaeri48nD6E= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/getkin/kin-openapi v0.80.0 h1:W/s5/DNnDCR8P+pYyafEWlGk4S7/AfQUWXgrRSSAzf8= -github.com/getkin/kin-openapi v0.80.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= -github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= -github.com/go-chi/chi/v5 v5.0.2 h1:4xKeALZdMEsuI5s05PU2Bm89Uc5iM04qFubUCl5LfAQ= -github.com/go-chi/chi/v5 v5.0.2/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/cors v1.1.1 h1:eHuqxsIw89iXcWnWUN8R72JMibABJTN/4IOYI5WERvw= -github.com/go-chi/cors v1.1.1/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/getkin/kin-openapi v0.114.0 h1:ar7QiJpDdlR+zSyPjrLf8mNnpoFP/lI90XcywMCFNe8= +github.com/getkin/kin-openapi v0.114.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc= +github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= +github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= +github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU= +github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/goccy/go-json v0.7.8 h1:CvMH7LotYymYuLGEohBM1lTZWX4g6jzWUUl2aLFuBoE= -github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -216,7 +171,6 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -229,19 +183,19 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.5.1 h1:/+mFTs4AlwsJ/mJe8NDtKb7BxLtbZFpcn8vDsneEkwQ= -github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-containerregistry v0.13.0 h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k= +github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.1-0.20190318165438-c8c88dbee036 h1:Avad62mreCc9la5buHvHZXbvsY+GPYUVjd8xsi48FYY= github.com/google/go-querystring v1.0.1-0.20190318165438-c8c88dbee036/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gopacket v1.1.16-0.20190123011826-102d5ca2098c h1:eR3RuANqlK0CQoHJxUdXQNsco+gJykcti01+wqBCuPs= -github.com/google/gopacket v1.1.16-0.20190123011826-102d5ca2098c/go.mod h1:UCLx9mCmAwsVbn6qQl1WIEt2SO7Nd2fD0th1TBAsqBw= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -249,44 +203,44 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= +github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc= +github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -294,52 +248,40 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A= github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4= github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ= -github.com/lestrrat-go/codegen v1.0.2/go.mod h1:JhJw6OQAuPEfVKUCLItpaVLumDGWQznd1VaXrBk9TdM= -github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc= -github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE= +github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= +github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= github.com/lestrrat-go/iter v1.0.1 h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A= github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= -github.com/lestrrat-go/jwx v1.2.7 h1:wO7fEc3PW56wpQBMU5CyRkrk4DVsXxCoJg7oIm5HHE4= -github.com/lestrrat-go/jwx v1.2.7/go.mod h1:bw24IXWbavc0R2RsOtpXL7RtMyP589yZ1+L7kd09ZGA= +github.com/lestrrat-go/jwx v1.2.25 h1:tAx93jN2SdPvFn08fHNAhqFJazn5mBBOB8Zli0g0otA= +github.com/lestrrat-go/jwx v1.2.25/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY= github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lucas-clemente/quic-go v0.29.1 h1:Z+WMJ++qMLhvpFkRZA+jl3BTxUjm415YBmWanXB8zP0= github.com/lucas-clemente/quic-go v0.29.1/go.mod h1:CTcNfLYJS2UuRNB+zcNlgvkjBhxX6Hm3WUxxAQx2mgE= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= @@ -347,206 +289,170 @@ github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKA github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= github.com/marten-seemann/qtls-go1-19 v0.1.0 h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK5df3GufyYYU= github.com/marten-seemann/qtls-go1-19 v0.1.0/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI= -github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= -github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 h1:aFkJ6lx4FPip+S+Uw4aTegFMct9shDvP+79PsSxpm3w= -github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= -github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/patrickmn/go-cache v2.1.1-0.20180815053127-5633e0862627+incompatible h1:MUIwjEiAMYk8zkXXUQeb5itrXF+HpS2pfxNsA2a7AiY= github.com/patrickmn/go-cache v2.1.1-0.20180815053127-5633e0862627+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= -github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw= +github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.0 h1:HRmM4uANZDAjdvbsdfOoqI5UDbjz0faKeMs/cGPKKI0= -github.com/prometheus/common v0.32.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8= -github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= -github.com/smartystreets/goconvey v1.6.7 h1:I6tZjLXD2Q1kjvNbIzB1wvQBsXmKXiVrhpRE8ZjP5jY= -github.com/smartystreets/goconvey v1.6.7/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b h1:+y4hCMc/WKsDbAPsOQZgBSaSZ26uh2afyaWeVg/3s/c= -github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= -github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= +github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= +github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= +github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= +github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8= +github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= +github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= +github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.10.0 h1:mXH0UwHS4D2HwWZa75im4xIQynLfblmWV7qcWpfv0yk= -github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= +github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= +github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4= -github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= +github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.0.0+incompatible h1:iMSCV0rmXEogjNWPh2D0xk9YVKvrtGoHJNe9ebLu/pw= github.com/uber/jaeger-lib v2.0.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 h1:cPXZWzzG0NllBLdjWoD1nDfaqu98YMv+OneaKc8sPOA= -github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= +github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= +github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= +go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE= go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA= go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= @@ -556,15 +462,13 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -589,8 +493,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -599,29 +502,26 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -638,18 +538,28 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -660,37 +570,30 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -707,45 +610,43 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -756,14 +657,11 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -783,28 +681,28 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -822,12 +720,16 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -852,20 +754,23 @@ google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -876,13 +781,14 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc/examples v0.0.0-20210630181457-52546c5d89b7 h1:mwWI8e38dmQeNvKtf/J7P9pdLzoXKnB0V5RBdMl0wNU= -google.golang.org/grpc/examples v0.0.0-20210630181457-52546c5d89b7/go.mod h1:bF8wuZSAZTcbF7ZPKrDI/qY52toTP/yxLpRRY4Eu9Js= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 h1:ijVKWXLMbG/RK63KfOQ1lEVpEApj174fkw073gxZf3w= +google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095/go.mod h1:Nr5H8+MlGWr5+xX/STzdoEqJrO+YteqFbMyCsrb6mH0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -895,38 +801,33 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= -gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -936,17 +837,6 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= inet.af/netaddr v0.0.0-20220811202034-502d2d690317 h1:U2fwK6P2EqmopP/hFLTOAjWTki0qgd4GMJn5X8wOleU= inet.af/netaddr v0.0.0-20220811202034-502d2d690317/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k= -k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/go_deps.bzl b/go_deps.bzl index 08bc34dcb..4de35e40d 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -31,12 +31,6 @@ def go_deps(): sum = "h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=", version = "v0.0.0-20190924025748-f65c72e2690d", ) - go_repository( - name = "com_github_antihax_optional", - importpath = "github.com/antihax/optional", - sum = "h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=", - version = "v1.0.0", - ) go_repository( name = "com_github_antlr_antlr4_runtime_go_antlr", importpath = "github.com/antlr/antlr4/runtime/Go/antlr", @@ -44,28 +38,34 @@ def go_deps(): version = "v0.0.0-20220209173558-ad29539cd2e9", ) go_repository( - name = "com_github_armon_consul_api", - importpath = "github.com/armon/consul-api", - sum = "h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA=", - version = "v0.0.0-20180202201655-eb2c6b5be1b6", + name = "com_github_apapsch_go_jsonmerge_v2", + importpath = "github.com/apapsch/go-jsonmerge/v2", + sum = "h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=", + version = "v2.0.0", ) go_repository( name = "com_github_armon_go_metrics", importpath = "github.com/armon/go-metrics", - sum = "h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo=", - version = "v0.3.10", + sum = "h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q=", + version = "v0.4.0", ) go_repository( name = "com_github_azure_go_ansiterm", importpath = "github.com/Azure/go-ansiterm", - sum = "h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=", - version = "v0.0.0-20170929234023-d6e3b3328b78", + sum = "h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=", + version = "v0.0.0-20210617225240-d185dfc1b5a1", ) go_repository( name = "com_github_bazelbuild_rules_go", importpath = "github.com/bazelbuild/rules_go", - sum = "h1:SfxjyO/V68rVnzOHop92fB0gv/Aa75KNLAN0PMqXbIw=", - version = "v0.29.0", + sum = "h1:YGNsLhWe18Ielebav7cClP3GMwBxBE+xEArLHtmXDx8=", + version = "v0.38.1", + ) + go_repository( + name = "com_github_benbjohnson_clock", + importpath = "github.com/benbjohnson/clock", + sum = "h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=", + version = "v1.1.0", ) go_repository( name = "com_github_beorn7_perks", @@ -73,11 +73,17 @@ def go_deps(): sum = "h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=", version = "v1.0.1", ) + go_repository( + name = "com_github_bmatcuk_doublestar", + importpath = "github.com/bmatcuk/doublestar", + sum = "h1:YroD6BJCZBYx06yYFEWvUuKVWQn3vLLQAVmDmvTSaiQ=", + version = "v1.1.1", + ) go_repository( name = "com_github_buildkite_go_buildkite_v2", importpath = "github.com/buildkite/go-buildkite/v2", - sum = "h1:aWsgMl3lA6xLSAyAhEO0DaHg7a7GVf/50mqVDC1Zt0A=", - version = "v2.8.1", + sum = "h1:K3eQZXm6ZFphKBIndOI+TnbluA8RDg5JMpwoFxSg3sc=", + version = "v2.9.0", ) go_repository( name = "com_github_burntsushi_toml", @@ -100,20 +106,14 @@ def go_deps(): go_repository( name = "com_github_census_instrumentation_opencensus_proto", importpath = "github.com/census-instrumentation/opencensus-proto", - sum = "h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk=", - version = "v0.3.0", - ) - go_repository( - name = "com_github_cespare_xxhash", - importpath = "github.com/cespare/xxhash", - sum = "h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=", - version = "v1.1.0", + sum = "h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=", + version = "v0.4.1", ) go_repository( name = "com_github_cespare_xxhash_v2", importpath = "github.com/cespare/xxhash/v2", - sum = "h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=", - version = "v2.1.2", + sum = "h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=", + version = "v2.2.0", ) go_repository( name = "com_github_chzyer_logex", @@ -142,14 +142,14 @@ def go_deps(): go_repository( name = "com_github_cncf_udpa_go", importpath = "github.com/cncf/udpa/go", - sum = "h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI=", - version = "v0.0.0-20210930031921-04548b0d99d4", + sum = "h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=", + version = "v0.0.0-20220112060539-c52dc94e7fbe", ) go_repository( name = "com_github_cncf_xds_go", importpath = "github.com/cncf/xds/go", - sum = "h1:KwaoQzs/WeUxxJqiJsZ4euOly1Az/IgZXXSxlD/UBNk=", - version = "v0.0.0-20211130200136-a8f946100490", + sum = "h1:ACGZRIr7HsgBKHsueQ1yM4WaVaXh21ynwqsF8M8tXhA=", + version = "v0.0.0-20230105202645-06c439db220b", ) go_repository( name = "com_github_codahale_hdrhistogram", @@ -157,29 +157,11 @@ def go_deps(): sum = "h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=", version = "v0.0.0-20161010025455-3a0bb77429bd", ) - go_repository( - name = "com_github_containerd_containerd", - importpath = "github.com/containerd/containerd", - sum = "h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY=", - version = "v1.3.0", - ) go_repository( name = "com_github_containerd_stargz_snapshotter_estargz", importpath = "github.com/containerd/stargz-snapshotter/estargz", - sum = "h1:5e7heayhB7CcgdTkqfZqrNaNv15gABwr3Q2jBTbLlt4=", - version = "v0.4.1", - ) - go_repository( - name = "com_github_coreos_bbolt", - importpath = "github.com/coreos/bbolt", - sum = "h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s=", - version = "v1.3.2", - ) - go_repository( - name = "com_github_coreos_etcd", - importpath = "github.com/coreos/etcd", - sum = "h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04=", - version = "v3.3.10+incompatible", + sum = "h1:+7nYmHJb0tEkcRaAW+MHqoKaJYZmkikupxCqVtmPuY0=", + version = "v0.12.1", ) go_repository( name = "com_github_coreos_go_semver", @@ -188,22 +170,16 @@ def go_deps(): version = "v0.3.0", ) go_repository( - name = "com_github_coreos_go_systemd", - importpath = "github.com/coreos/go-systemd", - sum = "h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=", - version = "v0.0.0-20190321100706-95778dfbb74e", - ) - go_repository( - name = "com_github_coreos_pkg", - importpath = "github.com/coreos/pkg", - sum = "h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=", - version = "v0.0.0-20180928190104-399ea9e2e55f", + name = "com_github_coreos_go_systemd_v22", + importpath = "github.com/coreos/go-systemd/v22", + sum = "h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=", + version = "v22.3.2", ) go_repository( name = "com_github_cpuguy83_go_md2man_v2", importpath = "github.com/cpuguy83/go-md2man/v2", - sum = "h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=", - version = "v2.0.1", + sum = "h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=", + version = "v2.0.2", ) go_repository( name = "com_github_creack_pty", @@ -211,12 +187,6 @@ def go_deps(): sum = "h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=", version = "v1.1.9", ) - go_repository( - name = "com_github_cyberdelia_templates", - importpath = "github.com/cyberdelia/templates", - sum = "h1:/ovYnF02fwL0kvspmy9AuyKg1JhdTRUgPw4nUxd9oZM=", - version = "v0.0.0-20141128023046-ca7fffd4298c", - ) go_repository( name = "com_github_davecgh_go_spew", importpath = "github.com/davecgh/go-spew", @@ -226,8 +196,8 @@ def go_deps(): go_repository( name = "com_github_dchest_cmac", importpath = "github.com/dchest/cmac", - sum = "h1:qoavXEzRRUfup81LsDQv4fnUQbLyorpPz6WxiwdiU7A=", - version = "v0.0.0-20150527144652-62ff55a1048c", + sum = "h1:Vaorm9FVpO2P+YmRdH0RVCUB1XF3Ge1yg9scPvJphyk=", + version = "v1.0.0", ) go_repository( name = "com_github_decred_dcrd_crypto_blake256", @@ -238,50 +208,38 @@ def go_deps(): go_repository( name = "com_github_decred_dcrd_dcrec_secp256k1_v4", importpath = "github.com/decred/dcrd/dcrec/secp256k1/v4", - sum = "h1:1iy2qD6JEhHKKhUOA9IWs7mjco7lnw2qx8FsRI2wirE=", - version = "v4.0.0-20210816181553-5444fa50b93d", + sum = "h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=", + version = "v4.0.1", ) go_repository( name = "com_github_deepmap_oapi_codegen", importpath = "github.com/deepmap/oapi-codegen", - sum = "h1:qpyRY+dzjMai5QejjA53ebnBtcSvIcZOtYwVlsgdxOc=", - version = "v1.9.0", - ) - go_repository( - name = "com_github_dgrijalva_jwt_go", - importpath = "github.com/dgrijalva/jwt-go", - sum = "h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=", - version = "v3.2.0+incompatible", - ) - go_repository( - name = "com_github_dgryski_go_sip13", - importpath = "github.com/dgryski/go-sip13", - sum = "h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4=", - version = "v0.0.0-20181026042036-e10d5fee7954", + sum = "h1:LDDxTtOtlGKTubzsuonFRmhMgP5zfWmM+G3Ql948TAs=", + version = "v1.12.5-0.20230221180206-2b52cd58cf5b", ) go_repository( name = "com_github_docker_cli", importpath = "github.com/docker/cli", - sum = "h1:2HQmlpI3yI9deH18Q6xiSOIjXD4sLI55Y/gfpa8/558=", - version = "v0.0.0-20191017083524-a8ff7f821017", + sum = "h1:lWQbHSHUFs7KraSN2jOJK7zbMS2jNCHI4mt4xUFUVQ4=", + version = "v20.10.20+incompatible", ) go_repository( name = "com_github_docker_distribution", importpath = "github.com/docker/distribution", - sum = "h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=", - version = "v2.7.1+incompatible", + sum = "h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=", + version = "v2.8.1+incompatible", ) go_repository( name = "com_github_docker_docker", importpath = "github.com/docker/docker", - sum = "h1:Cvj7S8I4Xpx78KAl6TwTmMHuHlZ/0SM60NUneGJQ7IE=", - version = "v1.4.2-0.20190924003213-a8608b5b67c7", + sum = "h1:kH9tx6XO+359d+iAkumyKDc5Q1kOwPuAUaeri48nD6E=", + version = "v20.10.20+incompatible", ) go_repository( name = "com_github_docker_docker_credential_helpers", importpath = "github.com/docker/docker-credential-helpers", - sum = "h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=", - version = "v0.6.3", + sum = "h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=", + version = "v0.7.0", ) go_repository( name = "com_github_docker_go_connections", @@ -292,14 +250,8 @@ def go_deps(): go_repository( name = "com_github_docker_go_units", importpath = "github.com/docker/go-units", - sum = "h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=", - version = "v0.4.0", - ) - go_repository( - name = "com_github_docopt_docopt_go", - importpath = "github.com/docopt/docopt-go", - sum = "h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=", - version = "v0.0.0-20180111231733-ee0de3bc6815", + sum = "h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=", + version = "v0.5.0", ) go_repository( name = "com_github_dvyukov_go_fuzz", @@ -307,29 +259,23 @@ def go_deps(): sum = "h1:q1oJaUPdmpDm/VyXosjgPgr6wS7c5iV2p0PwJD73bUI=", version = "v0.0.0-20210103155950-6a8e9d1f2415", ) - go_repository( - name = "com_github_emicklei_go_restful", - importpath = "github.com/emicklei/go-restful", - sum = "h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=", - version = "v2.9.5+incompatible", - ) go_repository( name = "com_github_envoyproxy_go_control_plane", importpath = "github.com/envoyproxy/go-control-plane", - sum = "h1:cgDRLG7bs59Zd+apAWuzLQL95obVYAymNJek76W3mgw=", - version = "v0.10.1", + sum = "h1:xdCVXxEe0Y3FQith+0cj2irwZudqGYvecuLB1HtdexY=", + version = "v0.10.3", ) go_repository( name = "com_github_envoyproxy_protoc_gen_validate", importpath = "github.com/envoyproxy/protoc-gen-validate", - sum = "h1:JiO+kJTpmYGjEodY7O1Zk8oZcNz1+f30UtwtXoFUPzE=", - version = "v0.6.2", + sum = "h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY=", + version = "v0.9.1", ) go_repository( name = "com_github_fatih_color", importpath = "github.com/fatih/color", - sum = "h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=", - version = "v1.13.0", + sum = "h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=", + version = "v1.14.1", ) go_repository( name = "com_github_francoispqt_gojay", @@ -337,23 +283,23 @@ def go_deps(): sum = "h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=", version = "v1.2.13", ) + go_repository( + name = "com_github_frankban_quicktest", + importpath = "github.com/frankban/quicktest", + sum = "h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=", + version = "v1.14.3", + ) go_repository( name = "com_github_fsnotify_fsnotify", importpath = "github.com/fsnotify/fsnotify", - sum = "h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=", - version = "v1.5.1", + sum = "h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=", + version = "v1.6.0", ) go_repository( name = "com_github_getkin_kin_openapi", importpath = "github.com/getkin/kin-openapi", - sum = "h1:W/s5/DNnDCR8P+pYyafEWlGk4S7/AfQUWXgrRSSAzf8=", - version = "v0.80.0", - ) - go_repository( - name = "com_github_ghodss_yaml", - importpath = "github.com/ghodss/yaml", - sum = "h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=", - version = "v1.0.0", + sum = "h1:ar7QiJpDdlR+zSyPjrLf8mNnpoFP/lI90XcywMCFNe8=", + version = "v0.114.0", ) go_repository( name = "com_github_gin_contrib_sse", @@ -364,20 +310,20 @@ def go_deps(): go_repository( name = "com_github_gin_gonic_gin", importpath = "github.com/gin-gonic/gin", - sum = "h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM=", - version = "v1.7.4", + sum = "h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=", + version = "v1.8.2", ) go_repository( name = "com_github_go_chi_chi_v5", importpath = "github.com/go-chi/chi/v5", - sum = "h1:4xKeALZdMEsuI5s05PU2Bm89Uc5iM04qFubUCl5LfAQ=", - version = "v5.0.2", + sum = "h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=", + version = "v5.0.8", ) go_repository( name = "com_github_go_chi_cors", importpath = "github.com/go-chi/cors", - sum = "h1:eHuqxsIw89iXcWnWUN8R72JMibABJTN/4IOYI5WERvw=", - version = "v1.1.1", + sum = "h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=", + version = "v1.2.1", ) go_repository( name = "com_github_go_gl_glfw", @@ -400,20 +346,14 @@ def go_deps(): go_repository( name = "com_github_go_kit_log", importpath = "github.com/go-kit/log", - sum = "h1:DGJh0Sm43HbOeYDNnVZFl8BvcYVvjD5bqYJvp0REbwQ=", - version = "v0.1.0", + sum = "h1:7i2K3eKTos3Vc0enKCfnVcgHh2olr/MyfboYq7cAcFw=", + version = "v0.2.0", ) go_repository( name = "com_github_go_logfmt_logfmt", importpath = "github.com/go-logfmt/logfmt", - sum = "h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=", - version = "v0.5.0", - ) - go_repository( - name = "com_github_go_logr_logr", - importpath = "github.com/go-logr/logr", - sum = "h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY=", - version = "v0.2.0", + sum = "h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=", + version = "v0.5.1", ) go_repository( name = "com_github_go_openapi_jsonpointer", @@ -421,29 +361,11 @@ def go_deps(): sum = "h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=", version = "v0.19.5", ) - go_repository( - name = "com_github_go_openapi_jsonreference", - importpath = "github.com/go-openapi/jsonreference", - sum = "h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o=", - version = "v0.19.3", - ) - go_repository( - name = "com_github_go_openapi_spec", - importpath = "github.com/go-openapi/spec", - sum = "h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc=", - version = "v0.19.3", - ) go_repository( name = "com_github_go_openapi_swag", importpath = "github.com/go-openapi/swag", - sum = "h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=", - version = "v0.19.14", - ) - go_repository( - name = "com_github_go_playground_assert_v2", - importpath = "github.com/go-playground/assert/v2", - sum = "h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=", - version = "v2.0.1", + sum = "h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=", + version = "v0.21.1", ) go_repository( name = "com_github_go_playground_locales", @@ -460,8 +382,8 @@ def go_deps(): go_repository( name = "com_github_go_playground_validator_v10", importpath = "github.com/go-playground/validator/v10", - sum = "h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A=", - version = "v10.9.0", + sum = "h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=", + version = "v10.11.1", ) go_repository( name = "com_github_go_stack_stack", @@ -475,11 +397,17 @@ def go_deps(): sum = "h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=", version = "v0.0.0-20210107165309-348f09dbbbc0", ) + go_repository( + name = "com_github_go_test_deep", + importpath = "github.com/go-test/deep", + sum = "h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=", + version = "v1.0.8", + ) go_repository( name = "com_github_goccy_go_json", importpath = "github.com/goccy/go-json", - sum = "h1:CvMH7LotYymYuLGEohBM1lTZWX4g6jzWUUl2aLFuBoE=", - version = "v0.7.8", + sum = "h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=", + version = "v0.9.11", ) go_repository( name = "com_github_gogo_protobuf", @@ -490,8 +418,8 @@ def go_deps(): go_repository( name = "com_github_golang_glog", importpath = "github.com/golang/glog", - sum = "h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=", - version = "v0.0.0-20160126235308-23def4e6c14b", + sum = "h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=", + version = "v1.0.0", ) go_repository( name = "com_github_golang_groupcache", @@ -499,6 +427,12 @@ def go_deps(): sum = "h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=", version = "v0.0.0-20210331224755-41bb18bfe9da", ) + go_repository( + name = "com_github_golang_jwt_jwt", + importpath = "github.com/golang-jwt/jwt", + sum = "h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=", + version = "v3.2.2+incompatible", + ) go_repository( name = "com_github_golang_mock", importpath = "github.com/golang/mock", @@ -526,14 +460,14 @@ def go_deps(): go_repository( name = "com_github_google_go_cmp", importpath = "github.com/google/go-cmp", - sum = "h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=", - version = "v0.5.8", + sum = "h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=", + version = "v0.5.9", ) go_repository( name = "com_github_google_go_containerregistry", importpath = "github.com/google/go-containerregistry", - sum = "h1:/+mFTs4AlwsJ/mJe8NDtKb7BxLtbZFpcn8vDsneEkwQ=", - version = "v0.5.1", + sum = "h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k=", + version = "v0.13.0", ) go_repository( name = "com_github_google_go_querystring", @@ -544,14 +478,14 @@ def go_deps(): go_repository( name = "com_github_google_gofuzz", importpath = "github.com/google/gofuzz", - sum = "h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=", - version = "v1.1.0", + sum = "h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=", + version = "v1.0.0", ) go_repository( name = "com_github_google_gopacket", importpath = "github.com/google/gopacket", - sum = "h1:eR3RuANqlK0CQoHJxUdXQNsco+gJykcti01+wqBCuPs=", - version = "v1.1.16-0.20190123011826-102d5ca2098c", + sum = "h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=", + version = "v1.1.19", ) go_repository( name = "com_github_google_martian", @@ -562,14 +496,14 @@ def go_deps(): go_repository( name = "com_github_google_martian_v3", importpath = "github.com/google/martian/v3", - sum = "h1:pMen7vLs8nvgEYhywH3KDWJIJTeEr2ULsVWHWYHQyBs=", - version = "v3.0.0", + sum = "h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60=", + version = "v3.1.0", ) go_repository( name = "com_github_google_pprof", importpath = "github.com/google/pprof", - sum = "h1:Ak8CrdlwwXwAZxzS66vgPt4U8yUZX7JwLvVR58FN5jM=", - version = "v0.0.0-20200708004538-1a94d8640e99", + sum = "h1:LR89qFljJ48s990kEKGsk213yIJDPI4205OKOzbURK8=", + version = "v0.0.0-20201218002935-b9804c9f04c2", ) go_repository( name = "com_github_google_renameio", @@ -580,20 +514,26 @@ def go_deps(): go_repository( name = "com_github_google_uuid", importpath = "github.com/google/uuid", - sum = "h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=", - version = "v1.1.2", + sum = "h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=", + version = "v1.3.0", + ) + go_repository( + name = "com_github_googleapis_enterprise_certificate_proxy", + importpath = "github.com/googleapis/enterprise-certificate-proxy", + sum = "h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg=", + version = "v0.2.1", ) go_repository( name = "com_github_googleapis_gax_go_v2", importpath = "github.com/googleapis/gax-go/v2", - sum = "h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU=", - version = "v2.1.1", + sum = "h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ=", + version = "v2.7.0", ) go_repository( - name = "com_github_googleapis_gnostic", - importpath = "github.com/googleapis/gnostic", - sum = "h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=", - version = "v0.4.1", + name = "com_github_googleapis_google_cloud_go_testing", + importpath = "github.com/googleapis/google-cloud-go-testing", + sum = "h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4=", + version = "v0.0.0-20200911160855-bcd43fbb19e8", ) go_repository( name = "com_github_gopherjs_gopherjs", @@ -607,12 +547,6 @@ def go_deps(): sum = "h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=", version = "v1.8.0", ) - go_repository( - name = "com_github_gorilla_websocket", - importpath = "github.com/gorilla/websocket", - sum = "h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=", - version = "v1.4.0", - ) go_repository( name = "com_github_grpc_ecosystem_go_grpc_middleware", importpath = "github.com/grpc-ecosystem/go-grpc-middleware", @@ -625,12 +559,6 @@ def go_deps(): sum = "h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=", version = "v1.2.0", ) - go_repository( - name = "com_github_grpc_ecosystem_grpc_gateway", - importpath = "github.com/grpc-ecosystem/grpc-gateway", - sum = "h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=", - version = "v1.16.0", - ) go_repository( name = "com_github_grpc_ecosystem_grpc_opentracing", importpath = "github.com/grpc-ecosystem/grpc-opentracing", @@ -640,8 +568,8 @@ def go_deps(): go_repository( name = "com_github_hashicorp_consul_api", importpath = "github.com/hashicorp/consul/api", - sum = "h1:Hw/G8TtRvOElqxVIhBzXciiSTbapq8hZ2XKZsXk5ZCE=", - version = "v1.11.0", + sum = "h1:R7PPNzTCeN6VuQNDwwhZWJvzCtGSrNpJqfb22h3yH9g=", + version = "v1.18.0", ) go_repository( name = "com_github_hashicorp_go_cleanhttp", @@ -652,8 +580,8 @@ def go_deps(): go_repository( name = "com_github_hashicorp_go_hclog", importpath = "github.com/hashicorp/go-hclog", - sum = "h1:bkKf0BeBXcSYa7f5Fyi9gMuQ8gNsxeiNpZjR6VxNZeo=", - version = "v1.0.0", + sum = "h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=", + version = "v1.2.0", ) go_repository( name = "com_github_hashicorp_go_immutable_radix", @@ -670,8 +598,8 @@ def go_deps(): go_repository( name = "com_github_hashicorp_golang_lru", importpath = "github.com/hashicorp/golang-lru", - sum = "h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=", - version = "v0.5.4", + sum = "h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4=", + version = "v0.6.0", ) go_repository( name = "com_github_hashicorp_hcl", @@ -682,8 +610,8 @@ def go_deps(): go_repository( name = "com_github_hashicorp_serf", importpath = "github.com/hashicorp/serf", - sum = "h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc=", - version = "v0.9.6", + sum = "h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=", + version = "v0.10.1", ) go_repository( name = "com_github_hpcloud_tail", @@ -700,25 +628,19 @@ def go_deps(): go_repository( name = "com_github_ianlancetaylor_demangle", importpath = "github.com/ianlancetaylor/demangle", - sum = "h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=", - version = "v0.0.0-20181102032728-5e5cf60278f6", + sum = "h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI=", + version = "v0.0.0-20200824232613-28f6c0f3b639", ) go_repository( name = "com_github_inconshreveable_mousetrap", importpath = "github.com/inconshreveable/mousetrap", - sum = "h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_joefitzgerald_rainbow_reporter", - importpath = "github.com/joefitzgerald/rainbow-reporter", - sum = "h1:AuMG652zjdzI0YCCnXAqATtRBpGXMcAnrajcaTrSeuo=", - version = "v0.1.0", + sum = "h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=", + version = "v1.0.1", ) go_repository( - name = "com_github_jonboulle_clockwork", - importpath = "github.com/jonboulle/clockwork", - sum = "h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=", + name = "com_github_invopop_yaml", + importpath = "github.com/invopop/yaml", + sum = "h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=", version = "v0.1.0", ) go_repository( @@ -751,6 +673,12 @@ def go_deps(): sum = "h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=", version = "v4.20.0+incompatible", ) + go_repository( + name = "com_github_juju_gnuflag", + importpath = "github.com/juju/gnuflag", + sum = "h1:c93kUJDtVAXFEhsCh5jSxyOJmFHuzcihnslQiX8Urwo=", + version = "v0.0.0-20171113085948-2ce1bb71843d", + ) go_repository( name = "com_github_julienschmidt_httprouter", importpath = "github.com/julienschmidt/httprouter", @@ -769,6 +697,12 @@ def go_deps(): sum = "h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=", version = "v1.0.0", ) + go_repository( + name = "com_github_klauspost_compress", + importpath = "github.com/klauspost/compress", + sum = "h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=", + version = "v1.15.11", + ) go_repository( name = "com_github_konsorten_go_windows_terminal_sequences", importpath = "github.com/konsorten/go-windows-terminal-sequences", @@ -796,8 +730,8 @@ def go_deps(): go_repository( name = "com_github_kr_pty", importpath = "github.com/kr/pty", - sum = "h1:hyz3dwM5QLc1Rfoz4FuWJQG5BN7tc6K1MndAUnGpQr4=", - version = "v1.1.5", + sum = "h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=", + version = "v1.1.1", ) go_repository( name = "com_github_kr_text", @@ -808,14 +742,14 @@ def go_deps(): go_repository( name = "com_github_labstack_echo_v4", importpath = "github.com/labstack/echo/v4", - sum = "h1:LF5Iq7t/jrtUuSutNuiEWtB5eiHfZ5gSe2pcu5exjQw=", - version = "v4.2.1", + sum = "h1:5CiyngihEO4HXsz3vVsJn7f8xAlWwRr3aY6Ih280ZKA=", + version = "v4.10.0", ) go_repository( name = "com_github_labstack_gommon", importpath = "github.com/labstack/gommon", - sum = "h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=", - version = "v0.3.0", + sum = "h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=", + version = "v0.4.0", ) go_repository( name = "com_github_leodido_go_urn", @@ -835,17 +769,11 @@ def go_deps(): sum = "h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4=", version = "v1.0.0", ) - go_repository( - name = "com_github_lestrrat_go_codegen", - importpath = "github.com/lestrrat-go/codegen", - sum = "h1:HWA03icqONV45riBbrVx+VOjL6esg4LUAuYlvpl/ZLU=", - version = "v1.0.2", - ) go_repository( name = "com_github_lestrrat_go_httpcc", importpath = "github.com/lestrrat-go/httpcc", - sum = "h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc=", - version = "v1.0.0", + sum = "h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=", + version = "v1.0.1", ) go_repository( name = "com_github_lestrrat_go_iter", @@ -856,8 +784,8 @@ def go_deps(): go_repository( name = "com_github_lestrrat_go_jwx", importpath = "github.com/lestrrat-go/jwx", - sum = "h1:wO7fEc3PW56wpQBMU5CyRkrk4DVsXxCoJg7oIm5HHE4=", - version = "v1.2.7", + sum = "h1:tAx93jN2SdPvFn08fHNAhqFJazn5mBBOB8Zli0g0otA=", + version = "v1.2.25", ) go_repository( name = "com_github_lestrrat_go_option", @@ -875,8 +803,8 @@ def go_deps(): go_repository( name = "com_github_magiconair_properties", importpath = "github.com/magiconair/properties", - sum = "h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=", - version = "v1.8.5", + sum = "h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=", + version = "v1.8.7", ) go_repository( name = "com_github_mailru_easyjson", @@ -905,20 +833,20 @@ def go_deps(): go_repository( name = "com_github_matryer_moq", importpath = "github.com/matryer/moq", - sum = "h1:HvFwW+cm9bCbZ/+vuGNq7CRWXql8c0y8nGeYpqmpvmk=", - version = "v0.0.0-20190312154309-6cfb0558e1bd", + sum = "h1:4j0goF/XK3pMTc7fJB3fveuTJoQNdavRX/78vlK3Xb4=", + version = "v0.3.0", ) go_repository( name = "com_github_mattn_go_colorable", importpath = "github.com/mattn/go-colorable", - sum = "h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=", - version = "v0.1.12", + sum = "h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=", + version = "v0.1.13", ) go_repository( name = "com_github_mattn_go_isatty", importpath = "github.com/mattn/go-isatty", - sum = "h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=", - version = "v0.0.14", + sum = "h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=", + version = "v0.0.17", ) go_repository( name = "com_github_mattn_go_runewidth", @@ -929,8 +857,8 @@ def go_deps(): go_repository( name = "com_github_mattn_go_sqlite3", importpath = "github.com/mattn/go-sqlite3", - sum = "h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI=", - version = "v1.14.4", + sum = "h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=", + version = "v1.14.16", ) go_repository( name = "com_github_matttproud_golang_protobuf_extensions", @@ -938,23 +866,11 @@ def go_deps(): sum = "h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=", version = "v1.0.1", ) - go_repository( - name = "com_github_maxbrunsfeld_counterfeiter_v6", - importpath = "github.com/maxbrunsfeld/counterfeiter/v6", - sum = "h1:g+4J5sZg6osfvEfkRZxJ1em0VT95/UOZgi/l7zi1/oE=", - version = "v6.2.2", - ) - go_repository( - name = "com_github_mdlayher_raw", - importpath = "github.com/mdlayher/raw", - sum = "h1:aFkJ6lx4FPip+S+Uw4aTegFMct9shDvP+79PsSxpm3w=", - version = "v0.0.0-20191009151244-50f2db8cc065", - ) go_repository( name = "com_github_microsoft_go_winio", importpath = "github.com/Microsoft/go-winio", - sum = "h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=", - version = "v0.4.14", + sum = "h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=", + version = "v0.6.0", ) go_repository( name = "com_github_mitchellh_go_homedir", @@ -965,8 +881,14 @@ def go_deps(): go_repository( name = "com_github_mitchellh_mapstructure", importpath = "github.com/mitchellh/mapstructure", - sum = "h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=", - version = "v1.4.3", + sum = "h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=", + version = "v1.5.0", + ) + go_repository( + name = "com_github_moby_term", + importpath = "github.com/moby/term", + sum = "h1:yH0SvLzcbZxcJXho2yh7CqdENGMQe73Cw3woZBpPli0=", + version = "v0.0.0-20210610120745-9d4ed1856297", ) go_repository( name = "com_github_modern_go_concurrent", @@ -980,18 +902,18 @@ def go_deps(): sum = "h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=", version = "v1.0.2", ) + go_repository( + name = "com_github_mohae_deepcopy", + importpath = "github.com/mohae/deepcopy", + sum = "h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=", + version = "v0.0.0-20170929034955-c48cc78d4826", + ) go_repository( name = "com_github_morikuni_aec", importpath = "github.com/morikuni/aec", sum = "h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=", version = "v1.0.0", ) - go_repository( - name = "com_github_munnerz_goautoneg", - importpath = "github.com/munnerz/goautoneg", - sum = "h1:7PxY7LVfSZm7PEeBTyK1rj1gABdCO2mbri6GKO1cMDs=", - version = "v0.0.0-20120707110453-a547fc61f48d", - ) go_repository( name = "com_github_mwitkow_go_conntrack", importpath = "github.com/mwitkow/go-conntrack", @@ -1010,30 +932,12 @@ def go_deps(): sum = "h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=", version = "v1.4.8", ) - go_repository( - name = "com_github_nytimes_gziphandler", - importpath = "github.com/NYTimes/gziphandler", - sum = "h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0=", - version = "v0.0.0-20170623195520-56545f4a5d46", - ) - go_repository( - name = "com_github_oklog_ulid", - importpath = "github.com/oklog/ulid", - sum = "h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=", - version = "v1.3.1", - ) go_repository( name = "com_github_olekukonko_tablewriter", importpath = "github.com/olekukonko/tablewriter", sum = "h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=", version = "v0.0.5", ) - go_repository( - name = "com_github_oneofone_xxhash", - importpath = "github.com/OneOfOne/xxhash", - sum = "h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=", - version = "v1.2.2", - ) go_repository( name = "com_github_onsi_ginkgo", importpath = "github.com/onsi/ginkgo", @@ -1055,8 +959,8 @@ def go_deps(): go_repository( name = "com_github_opencontainers_image_spec", importpath = "github.com/opencontainers/image-spec", - sum = "h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=", - version = "v1.0.1", + sum = "h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=", + version = "v1.1.0-rc2", ) go_repository( name = "com_github_opentracing_opentracing_go", @@ -1073,14 +977,20 @@ def go_deps(): go_repository( name = "com_github_pelletier_go_toml", importpath = "github.com/pelletier/go-toml", - sum = "h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=", - version = "v1.9.4", + sum = "h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=", + version = "v1.9.5", + ) + go_repository( + name = "com_github_pelletier_go_toml_v2", + importpath = "github.com/pelletier/go-toml/v2", + sum = "h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=", + version = "v2.0.6", ) go_repository( - name = "com_github_pkg_diff", - importpath = "github.com/pkg/diff", - sum = "h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=", - version = "v0.0.0-20210226163009-20ebb0f2a09e", + name = "com_github_perimeterx_marshmallow", + importpath = "github.com/perimeterx/marshmallow", + sum = "h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw=", + version = "v1.1.4", ) go_repository( name = "com_github_pkg_errors", @@ -1091,8 +1001,8 @@ def go_deps(): go_repository( name = "com_github_pkg_sftp", importpath = "github.com/pkg/sftp", - sum = "h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc=", - version = "v1.10.1", + sum = "h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=", + version = "v1.13.1", ) go_repository( name = "com_github_pmezard_go_difflib", @@ -1103,56 +1013,38 @@ def go_deps(): go_repository( name = "com_github_prometheus_client_golang", importpath = "github.com/prometheus/client_golang", - sum = "h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s=", - version = "v1.11.1", + sum = "h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=", + version = "v1.14.0", ) go_repository( name = "com_github_prometheus_client_model", importpath = "github.com/prometheus/client_model", - sum = "h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=", - version = "v0.2.0", + sum = "h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=", + version = "v0.3.0", ) go_repository( name = "com_github_prometheus_common", importpath = "github.com/prometheus/common", - sum = "h1:HRmM4uANZDAjdvbsdfOoqI5UDbjz0faKeMs/cGPKKI0=", - version = "v0.32.0", + sum = "h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=", + version = "v0.37.0", ) go_repository( name = "com_github_prometheus_procfs", importpath = "github.com/prometheus/procfs", - sum = "h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=", - version = "v0.6.0", + sum = "h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=", + version = "v0.8.0", ) go_repository( - name = "com_github_prometheus_tsdb", - importpath = "github.com/prometheus/tsdb", - sum = "h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=", - version = "v0.7.1", - ) - go_repository( - name = "com_github_puerkitobio_purell", - importpath = "github.com/PuerkitoBio/purell", - sum = "h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_puerkitobio_urlesc", - importpath = "github.com/PuerkitoBio/urlesc", - sum = "h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=", - version = "v0.0.0-20170810143723-de5bf2ad4578", - ) - go_repository( - name = "com_github_rogpeppe_fastuuid", - importpath = "github.com/rogpeppe/fastuuid", - sum = "h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=", - version = "v1.2.0", + name = "com_github_ravenox_go_jsoncommentstrip", + importpath = "github.com/RaveNoX/go-jsoncommentstrip", + sum = "h1:t527LHHE3HmiHrq74QMpNPZpGCIJzTx+apLkMKt4HC0=", + version = "v1.0.0", ) go_repository( name = "com_github_rogpeppe_go_internal", importpath = "github.com/rogpeppe/go-internal", - sum = "h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=", - version = "v1.8.0", + sum = "h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=", + version = "v1.6.1", ) go_repository( name = "com_github_russross_blackfriday_v2", @@ -1163,80 +1055,56 @@ def go_deps(): go_repository( name = "com_github_sagikazarmark_crypt", importpath = "github.com/sagikazarmark/crypt", - sum = "h1:TV5DVog+pihN4Rr0rN1IClv4ePpkzdg9sPrw7WDofZ8=", - version = "v0.3.0", - ) - go_repository( - name = "com_github_sclevine_spec", - importpath = "github.com/sclevine/spec", - sum = "h1:1Jwdf9jSfDl9NVmt8ndHqbTZ7XCCPbh1jI3hkDBHVYA=", - version = "v1.2.0", + sum = "h1:fipzMFW34hFUEc4D7fsLQFtE7yElkpgyS2zruedRdZk=", + version = "v0.9.0", ) go_repository( name = "com_github_sergi_go_diff", importpath = "github.com/sergi/go-diff", - sum = "h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_shurcool_sanitized_anchor_name", - importpath = "github.com/shurcooL/sanitized_anchor_name", - sum = "h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=", - version = "v1.0.0", + sum = "h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=", + version = "v1.3.1", ) go_repository( name = "com_github_sirupsen_logrus", importpath = "github.com/sirupsen/logrus", - sum = "h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=", - version = "v1.6.0", + sum = "h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=", + version = "v1.9.0", ) go_repository( name = "com_github_smartystreets_assertions", importpath = "github.com/smartystreets/assertions", - sum = "h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=", - version = "v1.0.0", + sum = "h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=", + version = "v1.2.0", ) go_repository( name = "com_github_smartystreets_goconvey", importpath = "github.com/smartystreets/goconvey", - sum = "h1:I6tZjLXD2Q1kjvNbIzB1wvQBsXmKXiVrhpRE8ZjP5jY=", - version = "v1.6.7", - ) - go_repository( - name = "com_github_soheilhy_cmux", - importpath = "github.com/soheilhy/cmux", - sum = "h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=", - version = "v0.1.4", + sum = "h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=", + version = "v1.7.2", ) go_repository( name = "com_github_songgao_water", importpath = "github.com/songgao/water", - sum = "h1:+y4hCMc/WKsDbAPsOQZgBSaSZ26uh2afyaWeVg/3s/c=", - version = "v0.0.0-20190725173103-fd331bda3f4b", - ) - go_repository( - name = "com_github_spaolacci_murmur3", - importpath = "github.com/spaolacci/murmur3", - sum = "h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=", - version = "v0.0.0-20180118202830-f09979ecbc72", + sum = "h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=", + version = "v0.0.0-20200317203138-2b4b6d7c09d8", ) go_repository( name = "com_github_spf13_afero", importpath = "github.com/spf13/afero", - sum = "h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=", - version = "v1.6.0", + sum = "h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=", + version = "v1.9.3", ) go_repository( name = "com_github_spf13_cast", importpath = "github.com/spf13/cast", - sum = "h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=", - version = "v1.4.1", + sum = "h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=", + version = "v1.5.0", ) go_repository( name = "com_github_spf13_cobra", importpath = "github.com/spf13/cobra", - sum = "h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=", - version = "v1.4.0", + sum = "h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=", + version = "v1.6.1", ) go_repository( name = "com_github_spf13_jwalterweatherman", @@ -1253,38 +1121,38 @@ def go_deps(): go_repository( name = "com_github_spf13_viper", importpath = "github.com/spf13/viper", - sum = "h1:mXH0UwHS4D2HwWZa75im4xIQynLfblmWV7qcWpfv0yk=", - version = "v1.10.0", + sum = "h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=", + version = "v1.15.0", + ) + go_repository( + name = "com_github_spkg_bom", + importpath = "github.com/spkg/bom", + sum = "h1:fiWzISvDn0Csy5H0iwgAuJGQTUpVfEMJJd4nRFXogbc=", + version = "v0.0.0-20160624110644-59b7046e48ad", ) go_repository( name = "com_github_stretchr_objx", importpath = "github.com/stretchr/objx", - sum = "h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=", - version = "v0.2.0", + sum = "h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=", + version = "v0.5.0", ) go_repository( name = "com_github_stretchr_testify", importpath = "github.com/stretchr/testify", - sum = "h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=", - version = "v1.7.0", + sum = "h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=", + version = "v1.8.1", ) go_repository( name = "com_github_subosito_gotenv", importpath = "github.com/subosito/gotenv", - sum = "h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_tmc_grpc_websocket_proxy", - importpath = "github.com/tmc/grpc-websocket-proxy", - sum = "h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=", - version = "v0.0.0-20190109142713-0ad062ec5ee5", + sum = "h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=", + version = "v1.4.2", ) go_repository( name = "com_github_uber_jaeger_client_go", importpath = "github.com/uber/jaeger-client-go", - sum = "h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4=", - version = "v2.29.1+incompatible", + sum = "h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=", + version = "v2.30.0+incompatible", ) go_repository( name = "com_github_uber_jaeger_lib", @@ -1295,14 +1163,14 @@ def go_deps(): go_repository( name = "com_github_ugorji_go", importpath = "github.com/ugorji/go", - sum = "h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=", - version = "v1.2.6", + sum = "h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=", + version = "v1.2.7", ) go_repository( name = "com_github_ugorji_go_codec", importpath = "github.com/ugorji/go/codec", - sum = "h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=", - version = "v1.2.6", + sum = "h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=", + version = "v1.2.7", ) go_repository( name = "com_github_valyala_bytebufferpool", @@ -1313,14 +1181,20 @@ def go_deps(): go_repository( name = "com_github_valyala_fasttemplate", importpath = "github.com/valyala/fasttemplate", - sum = "h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=", - version = "v1.2.1", + sum = "h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=", + version = "v1.2.2", + ) + go_repository( + name = "com_github_vbatts_tar_split", + importpath = "github.com/vbatts/tar-split", + sum = "h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME=", + version = "v0.11.2", ) go_repository( name = "com_github_vishvananda_netlink", importpath = "github.com/vishvananda/netlink", - sum = "h1:cPXZWzzG0NllBLdjWoD1nDfaqu98YMv+OneaKc8sPOA=", - version = "v1.1.1-0.20201029203352-d40f9887b852", + sum = "h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=", + version = "v1.2.1-beta.2", ) go_repository( name = "com_github_vishvananda_netns", @@ -1328,192 +1202,822 @@ def go_deps(): sum = "h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=", version = "v0.0.0-20200728191858-db3c7e526aae", ) - go_repository( - name = "com_github_xiang90_probing", - importpath = "github.com/xiang90/probing", - sum = "h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=", - version = "v0.0.0-20190116061207-43a291ad63a2", - ) - go_repository( - name = "com_github_xordataexchange_crypt", - importpath = "github.com/xordataexchange/crypt", - sum = "h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow=", - version = "v0.0.3-0.20170626215501-b2862e3d0a77", - ) go_repository( name = "com_github_yuin_goldmark", importpath = "github.com/yuin/goldmark", - sum = "h1:/vn0k+RBvwlxEmP5E7SZMqNxPhfMVFEJiykr15/0XKM=", - version = "v1.4.1", + sum = "h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=", + version = "v1.4.13", ) go_repository( name = "com_google_cloud_go", importpath = "cloud.google.com/go", - sum = "h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY=", - version = "v0.99.0", + sum = "h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=", + version = "v0.105.0", ) go_repository( - name = "com_google_cloud_go_bigquery", - importpath = "cloud.google.com/go/bigquery", - sum = "h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA=", - version = "v1.8.0", + name = "com_google_cloud_go_accessapproval", + importpath = "cloud.google.com/go/accessapproval", + sum = "h1:/nTivgnV/n1CaAeo+ekGexTYUsKEU9jUVkoY5359+3Q=", + version = "v1.5.0", ) go_repository( - name = "com_google_cloud_go_datastore", - importpath = "cloud.google.com/go/datastore", - sum = "h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=", - version = "v1.1.0", + name = "com_google_cloud_go_accesscontextmanager", + importpath = "cloud.google.com/go/accesscontextmanager", + sum = "h1:CFhNhU7pcD11cuDkQdrE6PQJgv0EXNKNv06jIzbLlCU=", + version = "v1.4.0", ) go_repository( - name = "com_google_cloud_go_firestore", - importpath = "cloud.google.com/go/firestore", - sum = "h1:8rBq3zRjnHx8UtBvaOWqBB1xq9jH6/wltfQLlTMh2Fw=", - version = "v1.6.1", + name = "com_google_cloud_go_aiplatform", + importpath = "cloud.google.com/go/aiplatform", + sum = "h1:DBi3Jk9XjCJ4pkkLM4NqKgj3ozUL1wq4l+d3/jTGXAI=", + version = "v1.27.0", ) go_repository( - name = "com_google_cloud_go_pubsub", - importpath = "cloud.google.com/go/pubsub", - sum = "h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=", - version = "v1.3.1", + name = "com_google_cloud_go_analytics", + importpath = "cloud.google.com/go/analytics", + sum = "h1:NKw6PpQi6V1O+KsjuTd+bhip9d0REYu4NevC45vtGp8=", + version = "v0.12.0", ) go_repository( - name = "com_google_cloud_go_storage", - importpath = "cloud.google.com/go/storage", - sum = "h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA=", - version = "v1.10.0", + name = "com_google_cloud_go_apigateway", + importpath = "cloud.google.com/go/apigateway", + sum = "h1:IIoXKR7FKrEAQhMTz5hK2wiDz2WNFHS7eVr/L1lE/rM=", + version = "v1.4.0", ) go_repository( - name = "com_shuralyov_dmitri_gpu_mtl", - importpath = "dmitri.shuralyov.com/gpu/mtl", - sum = "h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=", - version = "v0.0.0-20190408044501-666a987793e9", + name = "com_google_cloud_go_apigeeconnect", + importpath = "cloud.google.com/go/apigeeconnect", + sum = "h1:AONoTYJviyv1vS4IkvWzq69gEVdvHx35wKXc+e6wjZQ=", + version = "v1.4.0", ) go_repository( - name = "in_gopkg_alecthomas_kingpin_v2", - importpath = "gopkg.in/alecthomas/kingpin.v2", - sum = "h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=", - version = "v2.2.6", + name = "com_google_cloud_go_appengine", + importpath = "cloud.google.com/go/appengine", + sum = "h1:lmG+O5oaR9xNwaRBwE2XoMhwQHsHql5IoiGr1ptdDwU=", + version = "v1.5.0", ) go_repository( - name = "in_gopkg_check_v1", - importpath = "gopkg.in/check.v1", - sum = "h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=", - version = "v1.0.0-20201130134442-10cb98267c6c", + name = "com_google_cloud_go_area120", + importpath = "cloud.google.com/go/area120", + sum = "h1:TCMhwWEWhCn8d44/Zs7UCICTWje9j3HuV6nVGMjdpYw=", + version = "v0.6.0", ) go_repository( - name = "in_gopkg_errgo_v2", - importpath = "gopkg.in/errgo.v2", - sum = "h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=", - version = "v2.1.0", + name = "com_google_cloud_go_artifactregistry", + importpath = "cloud.google.com/go/artifactregistry", + sum = "h1:3d0LRAU1K6vfqCahhl9fx2oGHcq+s5gftdix4v8Ibrc=", + version = "v1.9.0", ) go_repository( - name = "in_gopkg_fsnotify_v1", - importpath = "gopkg.in/fsnotify.v1", - sum = "h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=", - version = "v1.4.7", + name = "com_google_cloud_go_asset", + importpath = "cloud.google.com/go/asset", + sum = "h1:aCrlaLGJWTODJX4G56ZYzJefITKEWNfbjjtHSzWpxW0=", + version = "v1.10.0", ) go_repository( - name = "in_gopkg_ini_v1", - importpath = "gopkg.in/ini.v1", - sum = "h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=", - version = "v1.66.2", + name = "com_google_cloud_go_assuredworkloads", + importpath = "cloud.google.com/go/assuredworkloads", + sum = "h1:hhIdCOowsT1GG5eMCIA0OwK6USRuYTou/1ZeNxCSRtA=", + version = "v1.9.0", ) go_repository( - name = "in_gopkg_resty_v1", - importpath = "gopkg.in/resty.v1", - sum = "h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI=", - version = "v1.12.0", + name = "com_google_cloud_go_automl", + importpath = "cloud.google.com/go/automl", + sum = "h1:BMioyXSbg7d7xLibn47cs0elW6RT780IUWr42W8rp2Q=", + version = "v1.8.0", ) go_repository( - name = "in_gopkg_tomb_v1", - importpath = "gopkg.in/tomb.v1", - sum = "h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=", - version = "v1.0.0-20141024135613-dd632973f1e7", + name = "com_google_cloud_go_baremetalsolution", + importpath = "cloud.google.com/go/baremetalsolution", + sum = "h1:g9KO6SkakcYPcc/XjAzeuUrEOXlYPnMpuiaywYaGrmQ=", + version = "v0.4.0", ) go_repository( - name = "in_gopkg_yaml_v2", - importpath = "gopkg.in/yaml.v2", - sum = "h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=", - version = "v2.4.0", + name = "com_google_cloud_go_batch", + importpath = "cloud.google.com/go/batch", + sum = "h1:1jvEBY55OH4Sd2FxEXQfxGExFWov1A/IaRe+Z5Z71Fw=", + version = "v0.4.0", ) go_repository( - name = "in_gopkg_yaml_v3", - importpath = "gopkg.in/yaml.v3", - sum = "h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=", - version = "v3.0.1", + name = "com_google_cloud_go_beyondcorp", + importpath = "cloud.google.com/go/beyondcorp", + sum = "h1:w+4kThysgl0JiKshi2MKDCg2NZgOyqOI0wq2eBZyrzA=", + version = "v0.3.0", ) go_repository( - name = "io_etcd_go_bbolt", - importpath = "go.etcd.io/bbolt", - sum = "h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=", - version = "v1.3.2", + name = "com_google_cloud_go_bigquery", + importpath = "cloud.google.com/go/bigquery", + sum = "h1:Wi4dITi+cf9VYp4VH2T9O41w0kCW0uQTELq2Z6tukN0=", + version = "v1.44.0", ) go_repository( - name = "io_etcd_go_etcd_api_v3", - importpath = "go.etcd.io/etcd/api/v3", - sum = "h1:v28cktvBq+7vGyJXF8G+rWJmj+1XUmMtqcLnH8hDocM=", - version = "v3.5.1", + name = "com_google_cloud_go_billing", + importpath = "cloud.google.com/go/billing", + sum = "h1:Xkii76HWELHwBtkQVZvqmSo9GTr0O+tIbRNnMcGdlg4=", + version = "v1.7.0", ) go_repository( - name = "io_etcd_go_etcd_client_pkg_v3", - importpath = "go.etcd.io/etcd/client/pkg/v3", - sum = "h1:XIQcHCFSG53bJETYeRJtIxdLv2EWRGxcfzR8lSnTH4E=", - version = "v3.5.1", + name = "com_google_cloud_go_binaryauthorization", + importpath = "cloud.google.com/go/binaryauthorization", + sum = "h1:pL70vXWn9TitQYXBWTK2abHl2JHLwkFRjYw6VflRqEA=", + version = "v1.4.0", ) go_repository( - name = "io_etcd_go_etcd_client_v2", - importpath = "go.etcd.io/etcd/client/v2", - sum = "h1:vtxYCKWA9x31w0WJj7DdqsHFNjhkigdAnziDtkZb/l4=", - version = "v2.305.1", + name = "com_google_cloud_go_certificatemanager", + importpath = "cloud.google.com/go/certificatemanager", + sum = "h1:tzbR4UHBbgsewMWUD93JHi8EBi/gHBoSAcY1/sThFGk=", + version = "v1.4.0", ) go_repository( - name = "io_k8s_code_generator", - importpath = "k8s.io/code-generator", - sum = "h1:kM/68Y26Z/u//TFc1ggVVcg62te8A2yQh57jBfD0FWQ=", - version = "v0.19.7", + name = "com_google_cloud_go_channel", + importpath = "cloud.google.com/go/channel", + sum = "h1:pNuUlZx0Jb0Ts9P312bmNMuH5IiFWIR4RUtLb70Ke5s=", + version = "v1.9.0", ) go_repository( - name = "io_k8s_gengo", - importpath = "k8s.io/gengo", - sum = "h1:JApXBKYyB7l9xx+DK7/+mFjC7A9Bt5A93FPvFD0HIFE=", - version = "v0.0.0-20201113003025-83324d819ded", + name = "com_google_cloud_go_cloudbuild", + importpath = "cloud.google.com/go/cloudbuild", + sum = "h1:TAAmCmAlOJ4uNBu6zwAjwhyl/7fLHHxIEazVhr3QBbQ=", + version = "v1.4.0", ) go_repository( - name = "io_k8s_klog_v2", - importpath = "k8s.io/klog/v2", - sum = "h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=", - version = "v2.4.0", + name = "com_google_cloud_go_clouddms", + importpath = "cloud.google.com/go/clouddms", + sum = "h1:UhzHIlgFfMr6luVYVNydw/pl9/U5kgtjCMJHnSvoVws=", + version = "v1.4.0", ) go_repository( - name = "io_k8s_kube_openapi", - importpath = "k8s.io/kube-openapi", - sum = "h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ=", - version = "v0.0.0-20200805222855-6aeccd4b50c6", + name = "com_google_cloud_go_cloudtasks", + importpath = "cloud.google.com/go/cloudtasks", + sum = "h1:faUiUgXjW8yVZ7XMnKHKm1WE4OldPBUWWfIRN/3z1dc=", + version = "v1.8.0", ) go_repository( - name = "io_k8s_sigs_structured_merge_diff_v4", - importpath = "sigs.k8s.io/structured-merge-diff/v4", - sum = "h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA=", - version = "v4.0.1", + name = "com_google_cloud_go_compute", + importpath = "cloud.google.com/go/compute", + sum = "h1:7UGq3QknM33pw5xATlpzeoomNxsacIVvTqTTvbfajmE=", + version = "v1.15.1", ) go_repository( - name = "io_k8s_sigs_yaml", - importpath = "sigs.k8s.io/yaml", - sum = "h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=", - version = "v1.2.0", + name = "com_google_cloud_go_compute_metadata", + importpath = "cloud.google.com/go/compute/metadata", + sum = "h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=", + version = "v0.2.3", ) go_repository( - name = "io_opencensus_go", - importpath = "go.opencensus.io", - sum = "h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=", - version = "v0.23.0", + name = "com_google_cloud_go_contactcenterinsights", + importpath = "cloud.google.com/go/contactcenterinsights", + sum = "h1:tTQLI/ZvguUf9Hv+36BkG2+/PeC8Ol1q4pBW+tgCx0A=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_container", + importpath = "cloud.google.com/go/container", + sum = "h1:nbEK/59GyDRKKlo1SqpohY1TK8LmJ2XNcvS9Gyom2A0=", + version = "v1.7.0", + ) + go_repository( + name = "com_google_cloud_go_containeranalysis", + importpath = "cloud.google.com/go/containeranalysis", + sum = "h1:2824iym832ljKdVpCBnpqm5K94YT/uHTVhNF+dRTXPI=", + version = "v0.6.0", ) go_repository( - name = "io_opentelemetry_go_proto_otlp", - importpath = "go.opentelemetry.io/proto/otlp", - sum = "h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8=", + name = "com_google_cloud_go_datacatalog", + importpath = "cloud.google.com/go/datacatalog", + sum = "h1:6kZ4RIOW/uT7QWC5SfPfq/G8sYzr/v+UOmOAxy4Z1TE=", + version = "v1.8.0", + ) + go_repository( + name = "com_google_cloud_go_dataflow", + importpath = "cloud.google.com/go/dataflow", + sum = "h1:CW3541Fm7KPTyZjJdnX6NtaGXYFn5XbFC5UcjgALKvU=", version = "v0.7.0", ) + go_repository( + name = "com_google_cloud_go_dataform", + importpath = "cloud.google.com/go/dataform", + sum = "h1:vLwowLF2ZB5J5gqiZCzv076lDI/Rd7zYQQFu5XO1PSg=", + version = "v0.5.0", + ) + go_repository( + name = "com_google_cloud_go_datafusion", + importpath = "cloud.google.com/go/datafusion", + sum = "h1:j5m2hjWovTZDTQak4MJeXAR9yN7O+zMfULnjGw/OOLg=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_datalabeling", + importpath = "cloud.google.com/go/datalabeling", + sum = "h1:dp8jOF21n/7jwgo/uuA0RN8hvLcKO4q6s/yvwevs2ZM=", + version = "v0.6.0", + ) + go_repository( + name = "com_google_cloud_go_dataplex", + importpath = "cloud.google.com/go/dataplex", + sum = "h1:cNxeA2DiWliQGi21kPRqnVeQ5xFhNoEjPRt1400Pm8Y=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_dataproc", + importpath = "cloud.google.com/go/dataproc", + sum = "h1:gVOqNmElfa6n/ccG/QDlfurMWwrK3ezvy2b2eDoCmS0=", + version = "v1.8.0", + ) + go_repository( + name = "com_google_cloud_go_dataqna", + importpath = "cloud.google.com/go/dataqna", + sum = "h1:gx9jr41ytcA3dXkbbd409euEaWtofCVXYBvJz3iYm18=", + version = "v0.6.0", + ) + go_repository( + name = "com_google_cloud_go_datastore", + importpath = "cloud.google.com/go/datastore", + sum = "h1:4siQRf4zTiAVt/oeH4GureGkApgb2vtPQAtOmhpqQwE=", + version = "v1.10.0", + ) + go_repository( + name = "com_google_cloud_go_datastream", + importpath = "cloud.google.com/go/datastream", + sum = "h1:PgIgbhedBtYBU6POGXFMn2uSl9vpqubc3ewTNdcU8Mk=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_deploy", + importpath = "cloud.google.com/go/deploy", + sum = "h1:kI6dxt8Ml0is/x7YZjLveTvR7YPzXAUD/8wQZ2nH5zA=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_dialogflow", + importpath = "cloud.google.com/go/dialogflow", + sum = "h1:HYHVOkoxQ9bSfNIelSZYNAtUi4CeSrCnROyOsbOqPq8=", + version = "v1.19.0", + ) + go_repository( + name = "com_google_cloud_go_dlp", + importpath = "cloud.google.com/go/dlp", + sum = "h1:9I4BYeJSVKoSKgjr70fLdRDumqcUeVmHV4fd5f9LR6Y=", + version = "v1.7.0", + ) + go_repository( + name = "com_google_cloud_go_documentai", + importpath = "cloud.google.com/go/documentai", + sum = "h1:jfq09Fdjtnpnmt/MLyf6A3DM3ynb8B2na0K+vSXvpFM=", + version = "v1.10.0", + ) + go_repository( + name = "com_google_cloud_go_domains", + importpath = "cloud.google.com/go/domains", + sum = "h1:pu3JIgC1rswIqi5romW0JgNO6CTUydLYX8zyjiAvO1c=", + version = "v0.7.0", + ) + go_repository( + name = "com_google_cloud_go_edgecontainer", + importpath = "cloud.google.com/go/edgecontainer", + sum = "h1:hd6J2n5dBBRuAqnNUEsKWrp6XNPKsaxwwIyzOPZTokk=", + version = "v0.2.0", + ) + go_repository( + name = "com_google_cloud_go_errorreporting", + importpath = "cloud.google.com/go/errorreporting", + sum = "h1:kj1XEWMu8P0qlLhm3FwcaFsUvXChV/OraZwA70trRR0=", + version = "v0.3.0", + ) + go_repository( + name = "com_google_cloud_go_essentialcontacts", + importpath = "cloud.google.com/go/essentialcontacts", + sum = "h1:b6csrQXCHKQmfo9h3dG/pHyoEh+fQG1Yg78a53LAviY=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_eventarc", + importpath = "cloud.google.com/go/eventarc", + sum = "h1:AgCqrmMMIcel5WWKkzz5EkCUKC3Rl5LNMMYsS+LvsI0=", + version = "v1.8.0", + ) + go_repository( + name = "com_google_cloud_go_filestore", + importpath = "cloud.google.com/go/filestore", + sum = "h1:yjKOpzvqtDmL5AXbKttLc8j0hL20kuC1qPdy5HPcxp0=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_firestore", + importpath = "cloud.google.com/go/firestore", + sum = "h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA=", + version = "v1.9.0", + ) + go_repository( + name = "com_google_cloud_go_functions", + importpath = "cloud.google.com/go/functions", + sum = "h1:35tgv1fQOtvKqH/uxJMzX3w6usneJ0zXpsFr9KAVhNE=", + version = "v1.9.0", + ) + go_repository( + name = "com_google_cloud_go_gaming", + importpath = "cloud.google.com/go/gaming", + sum = "h1:97OAEQtDazAJD7yh/kvQdSCQuTKdR0O+qWAJBZJ4xiA=", + version = "v1.8.0", + ) + go_repository( + name = "com_google_cloud_go_gkebackup", + importpath = "cloud.google.com/go/gkebackup", + sum = "h1:4K+jiv4ocqt1niN8q5Imd8imRoXBHTrdnJVt/uFFxF4=", + version = "v0.3.0", + ) + go_repository( + name = "com_google_cloud_go_gkeconnect", + importpath = "cloud.google.com/go/gkeconnect", + sum = "h1:zAcvDa04tTnGdu6TEZewaLN2tdMtUOJJ7fEceULjguA=", + version = "v0.6.0", + ) + go_repository( + name = "com_google_cloud_go_gkehub", + importpath = "cloud.google.com/go/gkehub", + sum = "h1:JTcTaYQRGsVm+qkah7WzHb6e9sf1C0laYdRPn9aN+vg=", + version = "v0.10.0", + ) + go_repository( + name = "com_google_cloud_go_gkemulticloud", + importpath = "cloud.google.com/go/gkemulticloud", + sum = "h1:8F1NhJj8ucNj7lK51UZMtAjSWTgP1zO18XF6vkfiPPU=", + version = "v0.4.0", + ) + go_repository( + name = "com_google_cloud_go_gsuiteaddons", + importpath = "cloud.google.com/go/gsuiteaddons", + sum = "h1:TGT2oGmO5q3VH6SjcrlgPUWI0njhYv4kywLm6jag0to=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_iam", + importpath = "cloud.google.com/go/iam", + sum = "h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk=", + version = "v0.8.0", + ) + go_repository( + name = "com_google_cloud_go_iap", + importpath = "cloud.google.com/go/iap", + sum = "h1:BGEXovwejOCt1zDk8hXq0bOhhRu9haXKWXXXp2B4wBM=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_ids", + importpath = "cloud.google.com/go/ids", + sum = "h1:LncHK4HHucb5Du310X8XH9/ICtMwZ2PCfK0ScjWiJoY=", + version = "v1.2.0", + ) + go_repository( + name = "com_google_cloud_go_iot", + importpath = "cloud.google.com/go/iot", + sum = "h1:Y9+oZT9jD4GUZzORXTU45XsnQrhxmDT+TFbPil6pRVQ=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_kms", + importpath = "cloud.google.com/go/kms", + sum = "h1:OWRZzrPmOZUzurjI2FBGtgY2mB1WaJkqhw6oIwSj0Yg=", + version = "v1.6.0", + ) + go_repository( + name = "com_google_cloud_go_language", + importpath = "cloud.google.com/go/language", + sum = "h1:3Wa+IUMamL4JH3Zd3cDZUHpwyqplTACt6UZKRD2eCL4=", + version = "v1.8.0", + ) + go_repository( + name = "com_google_cloud_go_lifesciences", + importpath = "cloud.google.com/go/lifesciences", + sum = "h1:tIqhivE2LMVYkX0BLgG7xL64oNpDaFFI7teunglt1tI=", + version = "v0.6.0", + ) + go_repository( + name = "com_google_cloud_go_logging", + importpath = "cloud.google.com/go/logging", + sum = "h1:ZBsZK+JG+oCDT+vaxwqF2egKNRjz8soXiS6Xv79benI=", + version = "v1.6.1", + ) + go_repository( + name = "com_google_cloud_go_longrunning", + importpath = "cloud.google.com/go/longrunning", + sum = "h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs=", + version = "v0.3.0", + ) + go_repository( + name = "com_google_cloud_go_managedidentities", + importpath = "cloud.google.com/go/managedidentities", + sum = "h1:3Kdajn6X25yWQFhFCErmKSYTSvkEd3chJROny//F1A0=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_maps", + importpath = "cloud.google.com/go/maps", + sum = "h1:kLReRbclTgJefw2fcCbdLPLhPj0U6UUWN10ldG8sdOU=", + version = "v0.1.0", + ) + go_repository( + name = "com_google_cloud_go_mediatranslation", + importpath = "cloud.google.com/go/mediatranslation", + sum = "h1:qAJzpxmEX+SeND10Y/4868L5wfZpo4Y3BIEnIieP4dk=", + version = "v0.6.0", + ) + go_repository( + name = "com_google_cloud_go_memcache", + importpath = "cloud.google.com/go/memcache", + sum = "h1:yLxUzJkZVSH2kPaHut7k+7sbIBFpvSh1LW9qjM2JDjA=", + version = "v1.7.0", + ) + go_repository( + name = "com_google_cloud_go_metastore", + importpath = "cloud.google.com/go/metastore", + sum = "h1:3KcShzqWdqxrDEXIBWpYJpOOrgpDj+HlBi07Grot49Y=", + version = "v1.8.0", + ) + go_repository( + name = "com_google_cloud_go_monitoring", + importpath = "cloud.google.com/go/monitoring", + sum = "h1:c9riaGSPQ4dUKWB+M1Fl0N+iLxstMbCktdEwYSPGDvA=", + version = "v1.8.0", + ) + go_repository( + name = "com_google_cloud_go_networkconnectivity", + importpath = "cloud.google.com/go/networkconnectivity", + sum = "h1:BVdIKaI68bihnXGdCVL89Jsg9kq2kg+II30fjVqo62E=", + version = "v1.7.0", + ) + go_repository( + name = "com_google_cloud_go_networkmanagement", + importpath = "cloud.google.com/go/networkmanagement", + sum = "h1:mDHA3CDW00imTvC5RW6aMGsD1bH+FtKwZm/52BxaiMg=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_networksecurity", + importpath = "cloud.google.com/go/networksecurity", + sum = "h1:qDEX/3sipg9dS5JYsAY+YvgTjPR63cozzAWop8oZS94=", + version = "v0.6.0", + ) + go_repository( + name = "com_google_cloud_go_notebooks", + importpath = "cloud.google.com/go/notebooks", + sum = "h1:AC8RPjNvel3ExgXjO1YOAz+teg9+j+89TNxa7pIZfww=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_optimization", + importpath = "cloud.google.com/go/optimization", + sum = "h1:7PxOq9VTT7TMib/6dMoWpMvWS2E4dJEvtYzjvBreaec=", + version = "v1.2.0", + ) + go_repository( + name = "com_google_cloud_go_orchestration", + importpath = "cloud.google.com/go/orchestration", + sum = "h1:39d6tqvNjd/wsSub1Bn4cEmrYcet5Ur6xpaN+SxOxtY=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_orgpolicy", + importpath = "cloud.google.com/go/orgpolicy", + sum = "h1:erF5PHqDZb6FeFrUHiYj2JK2BMhsk8CyAg4V4amJ3rE=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_osconfig", + importpath = "cloud.google.com/go/osconfig", + sum = "h1:NO0RouqCOM7M2S85Eal6urMSSipWwHU8evzwS+siqUI=", + version = "v1.10.0", + ) + go_repository( + name = "com_google_cloud_go_oslogin", + importpath = "cloud.google.com/go/oslogin", + sum = "h1:pKGDPfeZHDybtw48WsnVLjoIPMi9Kw62kUE5TXCLCN4=", + version = "v1.7.0", + ) + go_repository( + name = "com_google_cloud_go_phishingprotection", + importpath = "cloud.google.com/go/phishingprotection", + sum = "h1:OrwHLSRSZyaiOt3tnY33dsKSedxbMzsXvqB21okItNQ=", + version = "v0.6.0", + ) + go_repository( + name = "com_google_cloud_go_policytroubleshooter", + importpath = "cloud.google.com/go/policytroubleshooter", + sum = "h1:NQklJuOUoz1BPP+Epjw81COx7IISWslkZubz/1i0UN8=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_privatecatalog", + importpath = "cloud.google.com/go/privatecatalog", + sum = "h1:Vz86uiHCtNGm1DeC32HeG2VXmOq5JRYA3VRPf8ZEcSg=", + version = "v0.6.0", + ) + go_repository( + name = "com_google_cloud_go_pubsub", + importpath = "cloud.google.com/go/pubsub", + sum = "h1:q+J/Nfr6Qx4RQeu3rJcnN48SNC0qzlYzSeqkPq93VHs=", + version = "v1.27.1", + ) + go_repository( + name = "com_google_cloud_go_pubsublite", + importpath = "cloud.google.com/go/pubsublite", + sum = "h1:iqrD8vp3giTb7hI1q4TQQGj77cj8zzgmMPsTZtLnprM=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_recaptchaenterprise_v2", + importpath = "cloud.google.com/go/recaptchaenterprise/v2", + sum = "h1:UqzFfb/WvhwXGDF1eQtdHLrmni+iByZXY4h3w9Kdyv8=", + version = "v2.5.0", + ) + go_repository( + name = "com_google_cloud_go_recommendationengine", + importpath = "cloud.google.com/go/recommendationengine", + sum = "h1:6w+WxPf2LmUEqX0YyvfCoYb8aBYOcbIV25Vg6R0FLGw=", + version = "v0.6.0", + ) + go_repository( + name = "com_google_cloud_go_recommender", + importpath = "cloud.google.com/go/recommender", + sum = "h1:9kMZQGeYfcOD/RtZfcNKGKtoex3DdoB4zRgYU/WaIwE=", + version = "v1.8.0", + ) + go_repository( + name = "com_google_cloud_go_redis", + importpath = "cloud.google.com/go/redis", + sum = "h1:/zTwwBKIAD2DEWTrXZp8WD9yD/gntReF/HkPssVYd0U=", + version = "v1.10.0", + ) + go_repository( + name = "com_google_cloud_go_resourcemanager", + importpath = "cloud.google.com/go/resourcemanager", + sum = "h1:NDao6CHMwEZIaNsdWy+tuvHaavNeGP06o1tgrR0kLvU=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_resourcesettings", + importpath = "cloud.google.com/go/resourcesettings", + sum = "h1:eTzOwB13WrfF0kuzG2ZXCfB3TLunSHBur4s+HFU6uSM=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_retail", + importpath = "cloud.google.com/go/retail", + sum = "h1:N9fa//ecFUOEPsW/6mJHfcapPV0wBSwIUwpVZB7MQ3o=", + version = "v1.11.0", + ) + go_repository( + name = "com_google_cloud_go_run", + importpath = "cloud.google.com/go/run", + sum = "h1:AWPuzU7Xtaj3Jf+QarDWIs6AJ5hM1VFQ+F6Q+VZ6OT4=", + version = "v0.3.0", + ) + go_repository( + name = "com_google_cloud_go_scheduler", + importpath = "cloud.google.com/go/scheduler", + sum = "h1:K/mxOewgHGeKuATUJNGylT75Mhtjmx1TOkKukATqMT8=", + version = "v1.7.0", + ) + go_repository( + name = "com_google_cloud_go_secretmanager", + importpath = "cloud.google.com/go/secretmanager", + sum = "h1:xE6uXljAC1kCR8iadt9+/blg1fvSbmenlsDN4fT9gqw=", + version = "v1.9.0", + ) + go_repository( + name = "com_google_cloud_go_security", + importpath = "cloud.google.com/go/security", + sum = "h1:KSKzzJMyUoMRQzcz7azIgqAUqxo7rmQ5rYvimMhikqg=", + version = "v1.10.0", + ) + go_repository( + name = "com_google_cloud_go_securitycenter", + importpath = "cloud.google.com/go/securitycenter", + sum = "h1:QTVtk/Reqnx2bVIZtJKm1+mpfmwRwymmNvlaFez7fQY=", + version = "v1.16.0", + ) + go_repository( + name = "com_google_cloud_go_servicecontrol", + importpath = "cloud.google.com/go/servicecontrol", + sum = "h1:ImIzbOu6y4jL6ob65I++QzvqgFaoAKgHOG+RU9/c4y8=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_servicedirectory", + importpath = "cloud.google.com/go/servicedirectory", + sum = "h1:f7M8IMcVzO3T425AqlZbP3yLzeipsBHtRza8vVFYMhQ=", + version = "v1.7.0", + ) + go_repository( + name = "com_google_cloud_go_servicemanagement", + importpath = "cloud.google.com/go/servicemanagement", + sum = "h1:TpkCO5M7dhKSy1bKUD9o/sSEW/U1Gtx7opA1fsiMx0c=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_serviceusage", + importpath = "cloud.google.com/go/serviceusage", + sum = "h1:b0EwJxPJLpavSljMQh0RcdHsUrr5DQ+Nelt/3BAs5ro=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_shell", + importpath = "cloud.google.com/go/shell", + sum = "h1:b1LFhFBgKsG252inyhtmsUUZwchqSz3WTvAIf3JFo4g=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_spanner", + importpath = "cloud.google.com/go/spanner", + sum = "h1:NvdTpRwf7DTegbfFdPjAWyD7bOVu0VeMqcvR9aCQCAc=", + version = "v1.41.0", + ) + go_repository( + name = "com_google_cloud_go_speech", + importpath = "cloud.google.com/go/speech", + sum = "h1:yK0ocnFH4Wsf0cMdUyndJQ/hPv02oTJOxzi6AgpBy4s=", + version = "v1.9.0", + ) + go_repository( + name = "com_google_cloud_go_storage", + importpath = "cloud.google.com/go/storage", + sum = "h1:6RRlFMv1omScs6iq2hfE3IvgE+l6RfJPampq8UZc5TU=", + version = "v1.14.0", + ) + go_repository( + name = "com_google_cloud_go_storagetransfer", + importpath = "cloud.google.com/go/storagetransfer", + sum = "h1:fUe3OydbbvHcAYp07xY+2UpH4AermGbmnm7qdEj3tGE=", + version = "v1.6.0", + ) + go_repository( + name = "com_google_cloud_go_talent", + importpath = "cloud.google.com/go/talent", + sum = "h1:MrekAGxLqAeAol4Sc0allOVqUGO8j+Iim8NMvpiD7tM=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_texttospeech", + importpath = "cloud.google.com/go/texttospeech", + sum = "h1:ccPiHgTewxgyAeCWgQWvZvrLmbfQSFABTMAfrSPLPyY=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_tpu", + importpath = "cloud.google.com/go/tpu", + sum = "h1:ztIdKoma1Xob2qm6QwNh4Xi9/e7N3IfvtwG5AcNsj1g=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_trace", + importpath = "cloud.google.com/go/trace", + sum = "h1:qO9eLn2esajC9sxpqp1YKX37nXC3L4BfGnPS0Cx9dYo=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_translate", + importpath = "cloud.google.com/go/translate", + sum = "h1:AOYOH3MspzJ/bH1YXzB+xTE8fMpn3mwhLjugwGXvMPI=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_video", + importpath = "cloud.google.com/go/video", + sum = "h1:ttlvO4J5c1VGq6FkHqWPD/aH6PfdxujHt+muTJlW1Zk=", + version = "v1.9.0", + ) + go_repository( + name = "com_google_cloud_go_videointelligence", + importpath = "cloud.google.com/go/videointelligence", + sum = "h1:RPFgVVXbI2b5vnrciZjtsUgpNKVtHO/WIyXUhEfuMhA=", + version = "v1.9.0", + ) + go_repository( + name = "com_google_cloud_go_vision_v2", + importpath = "cloud.google.com/go/vision/v2", + sum = "h1:TQHxRqvLMi19azwm3qYuDbEzZWmiKJNTpGbkNsfRCik=", + version = "v2.5.0", + ) + go_repository( + name = "com_google_cloud_go_vmmigration", + importpath = "cloud.google.com/go/vmmigration", + sum = "h1:A2Tl2ZmwMRpvEmhV2ibISY85fmQR+Y5w9a0PlRz5P3s=", + version = "v1.3.0", + ) + go_repository( + name = "com_google_cloud_go_vmwareengine", + importpath = "cloud.google.com/go/vmwareengine", + sum = "h1:JMPZaOT/gIUxVlTqSl/QQ32Y2k+r0stNeM1NSqhVP9o=", + version = "v0.1.0", + ) + go_repository( + name = "com_google_cloud_go_vpcaccess", + importpath = "cloud.google.com/go/vpcaccess", + sum = "h1:woHXXtnW8b9gLFdWO9HLPalAddBQ9V4LT+1vjKwR3W8=", + version = "v1.5.0", + ) + go_repository( + name = "com_google_cloud_go_webrisk", + importpath = "cloud.google.com/go/webrisk", + sum = "h1:ypSnpGlJnZSXbN9a13PDmAYvVekBLnGKxQ3Q9SMwnYY=", + version = "v1.7.0", + ) + go_repository( + name = "com_google_cloud_go_websecurityscanner", + importpath = "cloud.google.com/go/websecurityscanner", + sum = "h1:y7yIFg/h/mO+5Y5aCOtVAnpGUOgqCH5rXQ2Oc8Oq2+g=", + version = "v1.4.0", + ) + go_repository( + name = "com_google_cloud_go_workflows", + importpath = "cloud.google.com/go/workflows", + sum = "h1:7Chpin9p50NTU8Tb7qk+I11U/IwVXmDhEoSsdccvInE=", + version = "v1.9.0", + ) + go_repository( + name = "com_shuralyov_dmitri_gpu_mtl", + importpath = "dmitri.shuralyov.com/gpu/mtl", + sum = "h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=", + version = "v0.0.0-20190408044501-666a987793e9", + ) + go_repository( + name = "in_gopkg_alecthomas_kingpin_v2", + importpath = "gopkg.in/alecthomas/kingpin.v2", + sum = "h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=", + version = "v2.2.6", + ) + go_repository( + name = "in_gopkg_check_v1", + importpath = "gopkg.in/check.v1", + sum = "h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=", + version = "v1.0.0-20201130134442-10cb98267c6c", + ) + go_repository( + name = "in_gopkg_errgo_v2", + importpath = "gopkg.in/errgo.v2", + sum = "h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=", + version = "v2.1.0", + ) + go_repository( + name = "in_gopkg_fsnotify_v1", + importpath = "gopkg.in/fsnotify.v1", + sum = "h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=", + version = "v1.4.7", + ) + go_repository( + name = "in_gopkg_ini_v1", + importpath = "gopkg.in/ini.v1", + sum = "h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=", + version = "v1.67.0", + ) + go_repository( + name = "in_gopkg_tomb_v1", + importpath = "gopkg.in/tomb.v1", + sum = "h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=", + version = "v1.0.0-20141024135613-dd632973f1e7", + ) + go_repository( + name = "in_gopkg_yaml_v2", + importpath = "gopkg.in/yaml.v2", + sum = "h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=", + version = "v2.4.0", + ) + go_repository( + name = "in_gopkg_yaml_v3", + importpath = "gopkg.in/yaml.v3", + sum = "h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=", + version = "v3.0.1", + ) + go_repository( + name = "io_etcd_go_etcd_api_v3", + importpath = "go.etcd.io/etcd/api/v3", + sum = "h1:Cy2qx3npLcYqTKqGJzMypnMv2tiRyifZJ17BlWIWA7A=", + version = "v3.5.6", + ) + go_repository( + name = "io_etcd_go_etcd_client_pkg_v3", + importpath = "go.etcd.io/etcd/client/pkg/v3", + sum = "h1:TXQWYceBKqLp4sa87rcPs11SXxUA/mHwH975v+BDvLU=", + version = "v3.5.6", + ) + go_repository( + name = "io_etcd_go_etcd_client_v2", + importpath = "go.etcd.io/etcd/client/v2", + sum = "h1:fIDR0p4KMjw01MJMfUIDWdQbjo06PD6CeYM5z4EHLi0=", + version = "v2.305.6", + ) + go_repository( + name = "io_etcd_go_etcd_client_v3", + importpath = "go.etcd.io/etcd/client/v3", + sum = "h1:coLs69PWCXE9G4FKquzNaSHrRyMCAXwF+IX1tAPVO8E=", + version = "v3.5.6", + ) + go_repository( + name = "io_opencensus_go", + importpath = "go.opencensus.io", + sum = "h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=", + version = "v0.24.0", + ) go_repository( name = "io_rsc_binaryregexp", importpath = "rsc.io/binaryregexp", @@ -1547,8 +2051,8 @@ def go_deps(): go_repository( name = "org_golang_google_api", importpath = "google.golang.org/api", - sum = "h1:PhGymJMXfGBzc4lBRmrx9+1w4w2wEzURHNGF/sD/xGc=", - version = "v0.62.0", + sum = "h1:I2SlFjD8ZWabaIFOfeEDg3pf0BHJDh6iYQ1ic3Yu/UU=", + version = "v0.107.0", ) go_repository( name = "org_golang_google_appengine", @@ -1559,32 +2063,32 @@ def go_deps(): go_repository( name = "org_golang_google_genproto", importpath = "google.golang.org/genproto", - sum = "h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0=", - version = "v0.0.0-20211208223120-3a66f561d7aa", + sum = "h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=", + version = "v0.0.0-20230110181048-76db0878b65f", ) go_repository( name = "org_golang_google_grpc", importpath = "google.golang.org/grpc", - sum = "h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=", - version = "v1.42.0", + sum = "h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=", + version = "v1.53.0", ) go_repository( name = "org_golang_google_grpc_examples", importpath = "google.golang.org/grpc/examples", - sum = "h1:mwWI8e38dmQeNvKtf/J7P9pdLzoXKnB0V5RBdMl0wNU=", - version = "v0.0.0-20210630181457-52546c5d89b7", + sum = "h1:ijVKWXLMbG/RK63KfOQ1lEVpEApj174fkw073gxZf3w=", + version = "v0.0.0-20230222033013-5353eaa44095", ) go_repository( name = "org_golang_google_protobuf", importpath = "google.golang.org/protobuf", - sum = "h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=", - version = "v1.27.1", + sum = "h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=", + version = "v1.28.1", ) go_repository( name = "org_golang_x_crypto", importpath = "golang.org/x/crypto", - sum = "h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=", - version = "v0.0.0-20210921155107-089bfa567519", + sum = "h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=", + version = "v0.6.0", ) go_repository( name = "org_golang_x_exp", @@ -1601,8 +2105,8 @@ def go_deps(): go_repository( name = "org_golang_x_lint", importpath = "golang.org/x/lint", - sum = "h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=", - version = "v0.0.0-20210508222113-6edffad5e616", + sum = "h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=", + version = "v0.0.0-20201208152925-83fdc39ff7b5", ) go_repository( name = "org_golang_x_mobile", @@ -1613,84 +2117,90 @@ def go_deps(): go_repository( name = "org_golang_x_mod", importpath = "golang.org/x/mod", - sum = "h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=", - version = "v0.6.0-dev.0.20220106191415-9b9b3d81d5e3", + sum = "h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=", + version = "v0.8.0", ) go_repository( name = "org_golang_x_net", importpath = "golang.org/x/net", - sum = "h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=", - version = "v0.0.0-20220624214902-1bab6f366d9e", + sum = "h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=", + version = "v0.7.0", ) go_repository( name = "org_golang_x_oauth2", importpath = "golang.org/x/oauth2", - sum = "h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=", - version = "v0.0.0-20211104180415-d3ed0bb246c8", + sum = "h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M=", + version = "v0.4.0", ) go_repository( name = "org_golang_x_sync", importpath = "golang.org/x/sync", - sum = "h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=", - version = "v0.0.0-20210220032951-036812b2e83c", + sum = "h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=", + version = "v0.1.0", ) go_repository( name = "org_golang_x_sys", importpath = "golang.org/x/sys", - sum = "h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=", - version = "v0.0.0-20220520151302-bc2c85ada10a", + sum = "h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=", + version = "v0.5.0", ) go_repository( name = "org_golang_x_term", importpath = "golang.org/x/term", - sum = "h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=", - version = "v0.0.0-20210927222741-03fcf44c2211", + sum = "h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=", + version = "v0.5.0", ) go_repository( name = "org_golang_x_text", importpath = "golang.org/x/text", - sum = "h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=", - version = "v0.3.7", + sum = "h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=", + version = "v0.7.0", ) go_repository( name = "org_golang_x_time", importpath = "golang.org/x/time", - sum = "h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=", - version = "v0.0.0-20210220033141-f8bda1e9f3ba", + sum = "h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=", + version = "v0.2.0", ) go_repository( name = "org_golang_x_tools", importpath = "golang.org/x/tools", - sum = "h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=", - version = "v0.1.10", + sum = "h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=", + version = "v0.6.0", + ) + go_repository( + name = "org_golang_x_xerrors", + importpath = "golang.org/x/xerrors", + sum = "h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=", + version = "v0.0.0-20220907171357-04be3eba64a2", ) go_repository( name = "org_uber_go_atomic", importpath = "go.uber.org/atomic", - sum = "h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=", - version = "v1.7.0", + sum = "h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=", + version = "v1.9.0", ) go_repository( name = "org_uber_go_goleak", importpath = "go.uber.org/goleak", - sum = "h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=", - version = "v1.1.10", + sum = "h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=", + version = "v1.2.1", ) go_repository( name = "org_uber_go_multierr", importpath = "go.uber.org/multierr", - sum = "h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=", - version = "v1.6.0", + sum = "h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=", + version = "v1.8.0", ) go_repository( name = "org_uber_go_zap", importpath = "go.uber.org/zap", - sum = "h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=", - version = "v1.17.0", + sum = "h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=", + version = "v1.24.0", ) go_repository( - name = "tools_gotest", - importpath = "gotest.tools", - sum = "h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=", - version = "v2.2.0+incompatible", + name = "tools_gotest_v3", + importpath = "gotest.tools/v3", + sum = "h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=", + version = "v3.0.3", ) diff --git a/licenses/data/com_github_apapsch_go_jsonmerge_v2/LICENSE b/licenses/data/com_github_apapsch_go_jsonmerge_v2/LICENSE new file mode 100644 index 000000000..f23057e46 --- /dev/null +++ b/licenses/data/com_github_apapsch_go_jsonmerge_v2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016-2019 Artur Kraev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/licenses/data/com_github_fsnotify_fsnotify/LICENSE b/licenses/data/com_github_fsnotify_fsnotify/LICENSE index e180c8fb0..fb03ade75 100644 --- a/licenses/data/com_github_fsnotify_fsnotify/LICENSE +++ b/licenses/data/com_github_fsnotify_fsnotify/LICENSE @@ -1,28 +1,25 @@ -Copyright (c) 2012 The Go Authors. All rights reserved. -Copyright (c) 2012-2019 fsnotify Authors. All rights reserved. +Copyright © 2012 The Go Authors. All rights reserved. +Copyright © fsnotify Authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/org_golang_x_xerrors/LICENSE b/licenses/data/com_github_google_uuid/LICENSE old mode 100755 new mode 100644 similarity index 96% rename from licenses/data/org_golang_x_xerrors/LICENSE rename to licenses/data/com_github_google_uuid/LICENSE index e4a47e17f..5dc68268d --- a/licenses/data/org_golang_x_xerrors/LICENSE +++ b/licenses/data/com_github_google_uuid/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019 The Go Authors. All rights reserved. +Copyright (c) 2009,2014 Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/licenses/data/com_github_hashicorp_golang_lru/LICENSE b/licenses/data/com_github_hashicorp_golang_lru/LICENSE index be2cc4dfb..0e5d580e0 100644 --- a/licenses/data/com_github_hashicorp_golang_lru/LICENSE +++ b/licenses/data/com_github_hashicorp_golang_lru/LICENSE @@ -1,3 +1,5 @@ +Copyright (c) 2014 HashiCorp, Inc. + Mozilla Public License, version 2.0 1. Definitions diff --git a/licenses/data/com_github_ghodss_yaml/LICENSE b/licenses/data/com_github_invopop_yaml/LICENSE similarity index 100% rename from licenses/data/com_github_ghodss_yaml/LICENSE rename to licenses/data/com_github_invopop_yaml/LICENSE diff --git a/licenses/data/com_github_labstack_echo_v4/LICENSE b/licenses/data/com_github_labstack_echo_v4/LICENSE index b5b006b4e..c46d0105f 100644 --- a/licenses/data/com_github_labstack_echo_v4/LICENSE +++ b/licenses/data/com_github_labstack_echo_v4/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2017 LabStack +Copyright (c) 2021 LabStack Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/licenses/data/com_github_mohae_deepcopy/LICENSE b/licenses/data/com_github_mohae_deepcopy/LICENSE new file mode 100644 index 000000000..419673f00 --- /dev/null +++ b/licenses/data/com_github_mohae_deepcopy/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Joel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/licenses/data/com_github_pelletier_go_toml_v2/LICENSE b/licenses/data/com_github_pelletier_go_toml_v2/LICENSE new file mode 100644 index 000000000..6839d51cd --- /dev/null +++ b/licenses/data/com_github_pelletier_go_toml_v2/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 - 2022 Thomas Pelletier, Eric Anderton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/licenses/data/com_github_perimeterx_marshmallow/LICENSE b/licenses/data/com_github_perimeterx_marshmallow/LICENSE new file mode 100644 index 000000000..8ffe86916 --- /dev/null +++ b/licenses/data/com_github_perimeterx_marshmallow/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 PerimeterX + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/licenses/data/in_gopkg_yaml_v3/LICENSE b/licenses/data/in_gopkg_yaml_v3/LICENSE new file mode 100644 index 000000000..2683e4bb1 --- /dev/null +++ b/licenses/data/in_gopkg_yaml_v3/LICENSE @@ -0,0 +1,50 @@ + +This project is covered by two different licenses: MIT and Apache. + +#### MIT License #### + +The following files were ported to Go from C files of libyaml, and thus +are still covered by their original MIT license, with the additional +copyright staring in 2011 when the project was ported over: + + apic.go emitterc.go parserc.go readerc.go scannerc.go + writerc.go yamlh.go yamlprivateh.go + +Copyright (c) 2006-2010 Kirill Simonov +Copyright (c) 2006-2011 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +### Apache License ### + +All the remaining project files are covered by the Apache license: + +Copyright (c) 2011-2019 Canonical Ltd + +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. diff --git a/licenses/data/org_uber_go_multierr/LICENSE.txt b/licenses/data/org_uber_go_multierr/LICENSE.txt index 858e02475..413e30f7c 100644 --- a/licenses/data/org_uber_go_multierr/LICENSE.txt +++ b/licenses/data/org_uber_go_multierr/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2017 Uber Technologies, Inc. +Copyright (c) 2017-2021 Uber Technologies, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/private/ca/api/BUILD.bazel b/private/ca/api/BUILD.bazel index 45184acaf..f23d09bbc 100644 --- a/private/ca/api/BUILD.bazel +++ b/private/ca/api/BUILD.bazel @@ -20,5 +20,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "@com_github_deepmap_oapi_codegen//pkg/runtime:go_default_library", # keep + "@com_github_deepmap_oapi_codegen//pkg/types:go_default_library", # keep ], ) diff --git a/private/ca/api/client.gen.go b/private/ca/api/client.gen.go index c0c805a1f..e32c482e3 100644 --- a/private/ca/api/client.gen.go +++ b/private/ca/api/client.gen.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -346,6 +345,10 @@ type PostAuthTokenResponse struct { Body []byte HTTPResponse *http.Response JSON200 *AccessToken + JSON400 *Problem + JSON401 *Problem + JSON500 *Problem + JSON503 *Problem } // Status returns HTTPResponse.Status @@ -368,6 +371,8 @@ type GetHealthcheckResponse struct { Body []byte HTTPResponse *http.Response JSON200 *HealthCheckStatus + JSON500 *Problem + JSON503 *Problem } // Status returns HTTPResponse.Status @@ -390,6 +395,11 @@ type PostCertificateRenewalResponse struct { Body []byte HTTPResponse *http.Response JSON200 *RenewalResponse + JSON400 *Problem + JSON401 *Problem + JSON404 *Problem + JSON500 *Problem + JSON503 *Problem } // Status returns HTTPResponse.Status @@ -453,7 +463,7 @@ func (c *ClientWithResponses) PostCertificateRenewalWithResponse(ctx context.Con // ParsePostAuthTokenResponse parses an HTTP response from a PostAuthTokenWithResponse call func ParsePostAuthTokenResponse(rsp *http.Response) (*PostAuthTokenResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -472,6 +482,34 @@ func ParsePostAuthTokenResponse(rsp *http.Response) (*PostAuthTokenResponse, err } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 503: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON503 = &dest + } return response, nil @@ -479,7 +517,7 @@ func ParsePostAuthTokenResponse(rsp *http.Response) (*PostAuthTokenResponse, err // ParseGetHealthcheckResponse parses an HTTP response from a GetHealthcheckWithResponse call func ParseGetHealthcheckResponse(rsp *http.Response) (*GetHealthcheckResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -498,6 +536,20 @@ func ParseGetHealthcheckResponse(rsp *http.Response) (*GetHealthcheckResponse, e } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 503: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON503 = &dest + } return response, nil @@ -505,7 +557,7 @@ func ParseGetHealthcheckResponse(rsp *http.Response) (*GetHealthcheckResponse, e // ParsePostCertificateRenewalResponse parses an HTTP response from a PostCertificateRenewalWithResponse call func ParsePostCertificateRenewalResponse(rsp *http.Response) (*PostCertificateRenewalResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -524,6 +576,41 @@ func ParsePostCertificateRenewalResponse(rsp *http.Response) (*PostCertificateRe } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 503: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON503 = &dest + } return response, nil diff --git a/private/ca/api/types.gen.go b/private/ca/api/types.gen.go index 266405117..db9693896 100644 --- a/private/ca/api/types.gen.go +++ b/private/ca/api/types.gen.go @@ -3,65 +3,69 @@ // Code generated by unknown module path version unknown version DO NOT EDIT. package api +import ( + "encoding/json" + + "github.com/deepmap/oapi-codegen/pkg/runtime" + openapi_types "github.com/deepmap/oapi-codegen/pkg/types" +) + const ( BearerAuthScopes = "BearerAuth.Scopes" ) // Defines values for AccessTokenTokenType. const ( - AccessTokenTokenTypeBearer AccessTokenTokenType = "Bearer" + Bearer AccessTokenTokenType = "Bearer" ) // Defines values for HealthCheckStatusStatus. const ( - HealthCheckStatusStatusAvailable HealthCheckStatusStatus = "available" - - HealthCheckStatusStatusStarting HealthCheckStatusStatus = "starting" - - HealthCheckStatusStatusStopping HealthCheckStatusStatus = "stopping" - - HealthCheckStatusStatusUnavailable HealthCheckStatusStatus = "unavailable" + Available HealthCheckStatusStatus = "available" + Starting HealthCheckStatusStatus = "starting" + Stopping HealthCheckStatusStatus = "stopping" + Unavailable HealthCheckStatusStatus = "unavailable" ) // AS defines model for AS. -type AS string +type AS = string // AccessCredentials defines model for AccessCredentials. type AccessCredentials struct { - // ID of the control service requesting authentication. + // ClientId ID of the control service requesting authentication. ClientId string `json:"client_id"` - // Secret that authenticates the control service. + // ClientSecret Secret that authenticates the control service. ClientSecret string `json:"client_secret"` } // AccessToken defines model for AccessToken. type AccessToken struct { - // The encoded JWT token + // AccessToken The encoded JWT token AccessToken string `json:"access_token"` - // Validity duration of this token in seconds. + // ExpiresIn Validity duration of this token in seconds. ExpiresIn int `json:"expires_in"` - // Type of returned access token. Currently always Bearer. + // TokenType Type of returned access token. Currently always Bearer. TokenType AccessTokenTokenType `json:"token_type"` } -// Type of returned access token. Currently always Bearer. +// AccessTokenTokenType Type of returned access token. Currently always Bearer. type AccessTokenTokenType string // CertificateChain defines model for CertificateChain. type CertificateChain struct { - // Base64 encoded AS certificate. + // AsCertificate Base64 encoded AS certificate. AsCertificate []byte `json:"as_certificate"` - // Base64 encoded CA certificate. + // CaCertificate Base64 encoded CA certificate. CaCertificate []byte `json:"ca_certificate"` } -// Certificate chain containing the the new AS certificate and the issuing +// CertificateChainPKCS7 Certificate chain containing the the new AS certificate and the issuing // CA certificate encoded in a degenerate PKCS#7 data structure. -type CertificateChainPKCS7 []byte +type CertificateChainPKCS7 = []byte // HealthCheckStatus defines model for HealthCheckStatus. type HealthCheckStatus struct { @@ -71,31 +75,31 @@ type HealthCheckStatus struct { // HealthCheckStatusStatus defines model for HealthCheckStatus.Status. type HealthCheckStatusStatus string -// Error message encoded as specified in +// Problem Error message encoded as specified in // [RFC7807](https://tools.ietf.org/html/rfc7807) type Problem struct { - // Identifier to correlate multiple error messages to the same case. - CorrelationId *string `json:"correlation_id,omitempty"` + // CorrelationId Identifier to correlate multiple error messages to the same case. + CorrelationId *openapi_types.UUID `json:"correlation_id,omitempty"` - // A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Detail A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Detail *string `json:"detail,omitempty"` - // A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. + // Instance A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. Instance *string `json:"instance,omitempty"` - // The HTTP status code generated by the server for this occurrence of the problem. + // Status The HTTP status code generated by the server for this occurrence of the problem. Status int `json:"status"` - // A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Title A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Title string `json:"title"` - // A URI reference that uniquely identifies the problem type in the context of the provided API. + // Type A URI reference that uniquely identifies the problem type in the context of the provided API. Type string `json:"type"` } // RenewalRequest defines model for RenewalRequest. type RenewalRequest struct { - // Base64 encoded renewal request as described below. + // Csr Base64 encoded renewal request as described below. // // The renewal requests consists of a CMS SignedData structure that // contains a PKCS#10 defining the parameters of the requested @@ -121,17 +125,78 @@ type RenewalRequest struct { // RenewalResponse defines model for RenewalResponse. type RenewalResponse struct { - CertificateChain interface{} `json:"certificate_chain"` + CertificateChain RenewalResponse_CertificateChain `json:"certificate_chain"` } -// PostAuthTokenJSONBody defines parameters for PostAuthToken. -type PostAuthTokenJSONBody AccessCredentials - -// PostCertificateRenewalJSONBody defines parameters for PostCertificateRenewal. -type PostCertificateRenewalJSONBody RenewalRequest +// RenewalResponse_CertificateChain defines model for RenewalResponse.CertificateChain. +type RenewalResponse_CertificateChain struct { + union json.RawMessage +} // PostAuthTokenJSONRequestBody defines body for PostAuthToken for application/json ContentType. -type PostAuthTokenJSONRequestBody PostAuthTokenJSONBody +type PostAuthTokenJSONRequestBody = AccessCredentials // PostCertificateRenewalJSONRequestBody defines body for PostCertificateRenewal for application/json ContentType. -type PostCertificateRenewalJSONRequestBody PostCertificateRenewalJSONBody +type PostCertificateRenewalJSONRequestBody = RenewalRequest + +// AsCertificateChain returns the union data inside the RenewalResponse_CertificateChain as a CertificateChain +func (t RenewalResponse_CertificateChain) AsCertificateChain() (CertificateChain, error) { + var body CertificateChain + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromCertificateChain overwrites any union data inside the RenewalResponse_CertificateChain as the provided CertificateChain +func (t *RenewalResponse_CertificateChain) FromCertificateChain(v CertificateChain) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeCertificateChain performs a merge with any union data inside the RenewalResponse_CertificateChain, using the provided CertificateChain +func (t *RenewalResponse_CertificateChain) MergeCertificateChain(v CertificateChain) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JsonMerge(b, t.union) + t.union = merged + return err +} + +// AsCertificateChainPKCS7 returns the union data inside the RenewalResponse_CertificateChain as a CertificateChainPKCS7 +func (t RenewalResponse_CertificateChain) AsCertificateChainPKCS7() (CertificateChainPKCS7, error) { + var body CertificateChainPKCS7 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromCertificateChainPKCS7 overwrites any union data inside the RenewalResponse_CertificateChain as the provided CertificateChainPKCS7 +func (t *RenewalResponse_CertificateChain) FromCertificateChainPKCS7(v CertificateChainPKCS7) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeCertificateChainPKCS7 performs a merge with any union data inside the RenewalResponse_CertificateChain, using the provided CertificateChainPKCS7 +func (t *RenewalResponse_CertificateChain) MergeCertificateChainPKCS7(v CertificateChainPKCS7) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JsonMerge(b, t.union) + t.union = merged + return err +} + +func (t RenewalResponse_CertificateChain) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *RenewalResponse_CertificateChain) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/private/ca/renewal/grpc/delegating_handler.go b/private/ca/renewal/grpc/delegating_handler.go index 0f26b05ce..80e1e989a 100644 --- a/private/ca/renewal/grpc/delegating_handler.go +++ b/private/ca/renewal/grpc/delegating_handler.go @@ -17,7 +17,6 @@ package grpc import ( "context" "crypto/x509" - "encoding/base64" "encoding/json" "fmt" "io" @@ -96,7 +95,7 @@ func (h *DelegatingHandler) HandleCMSRequest( rep, err := h.Client.PostCertificateRenewal( ctx, int(subject.ISD()), - api.AS(subject.AS().String()), + subject.AS().String(), api.PostCertificateRenewalJSONRequestBody{ Csr: req.CmsSignedRequest, }, @@ -145,39 +144,17 @@ func (h *DelegatingHandler) HandleCMSRequest( } func (h *DelegatingHandler) parseChain(rep api.RenewalResponse) ([]*x509.Certificate, error) { - switch content := rep.CertificateChain.(type) { - case string: - raw, err := base64.StdEncoding.DecodeString(content) - if err != nil { - return nil, serrors.WrapStr("malformed certificate_chain", err) - } - return extractChain(raw) - case map[string]interface{}: - decode := func(key string) ([]byte, error) { - b64, ok := content[key] - if !ok { - return nil, serrors.New("certificate missing") - } - s, ok := b64.(string) - if !ok { - return nil, serrors.New("wrong type", "type", fmt.Sprintf("%T", s)) - } - return base64.StdEncoding.DecodeString(s) - } - as, err := decode("as_certificate") - if err != nil { - return nil, serrors.WrapStr("parsing AS certificate", err, "key", "as_certificate") - } - ca, err := decode("ca_certificate") - if err != nil { - return nil, serrors.WrapStr("parsing AS certificate", err, "key", "ca_certificate") - } - return h.parseChainJSON(api.CertificateChain{ - AsCertificate: as, - CaCertificate: ca, - }) + chain, chainErr := rep.CertificateChain.AsCertificateChain() + pkcs7, pkcs7Err := rep.CertificateChain.AsCertificateChainPKCS7() + switch { + case chainErr == nil: + return h.parseChainJSON(chain) + case pkcs7Err == nil: + return extractChain(pkcs7) default: - return nil, serrors.New("certificate_chain unset", "type", fmt.Sprintf("%T", content)) + return nil, serrors.New("certificate_chain unset", + "chain_err", chainErr, "pkcs7_err", pkcs7Err, + ) } } diff --git a/private/ca/renewal/grpc/delegating_handler_test.go b/private/ca/renewal/grpc/delegating_handler_test.go index cd95c28ef..aaffdc85a 100644 --- a/private/ca/renewal/grpc/delegating_handler_test.go +++ b/private/ca/renewal/grpc/delegating_handler_test.go @@ -165,11 +165,14 @@ func TestDelegatingHandler(t *testing.T) { return dummyReq }, Client: func(t *testing.T, ctrl *gomock.Controller) renewalgrpc.CAServiceClient { + var apiChain api.RenewalResponse_CertificateChain + err := apiChain.FromCertificateChain(api.CertificateChain{ + AsCertificate: chain[0].Raw, + CaCertificate: chain[1].Raw, + }) + require.NoError(t, err) rep, err := json.Marshal(api.RenewalResponse{ - CertificateChain: api.CertificateChain{ - AsCertificate: chain[0].Raw, - CaCertificate: chain[1].Raw, - }, + CertificateChain: apiChain, }) require.NoError(t, err) diff --git a/private/ca/renewal/grpc/mock_grpc/mock.go b/private/ca/renewal/grpc/mock_grpc/mock.go index 8cce972e3..3e1809a77 100644 --- a/private/ca/renewal/grpc/mock_grpc/mock.go +++ b/private/ca/renewal/grpc/mock_grpc/mock.go @@ -191,7 +191,7 @@ func (m *MockCAServiceClient) EXPECT() *MockCAServiceClientMockRecorder { } // PostCertificateRenewal mocks base method. -func (m *MockCAServiceClient) PostCertificateRenewal(arg0 context.Context, arg1 int, arg2 api.AS, arg3 api.PostCertificateRenewalJSONRequestBody, arg4 ...api.RequestEditorFn) (*http.Response, error) { +func (m *MockCAServiceClient) PostCertificateRenewal(arg0 context.Context, arg1 int, arg2 string, arg3 api.RenewalRequest, arg4 ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() varargs := []interface{}{arg0, arg1, arg2, arg3} for _, a := range arg4 { diff --git a/private/mgmtapi/cppki/api/api.go b/private/mgmtapi/cppki/api/api.go index 9082c5c68..6bc14595b 100644 --- a/private/mgmtapi/cppki/api/api.go +++ b/private/mgmtapi/cppki/api/api.go @@ -49,7 +49,7 @@ func (s *Server) GetCertificates( q := trust.ChainQuery{Date: time.Now()} var errs serrors.List if params.IsdAs != nil { - if ia, err := addr.ParseIA(string(*params.IsdAs)); err == nil { + if ia, err := addr.ParseIA(*params.IsdAs); err == nil { q.IA = ia } else { errs = append(errs, serrors.WithCtx(err, "parameter", "isd_as")) @@ -91,9 +91,9 @@ func (s *Server) GetCertificates( continue } results = append(results, ChainBrief{ - Id: ChainID(fmt.Sprintf("%x", truststorage.ChainID(chain))), - Issuer: IsdAs(issuer.String()), - Subject: IsdAs(subject.String()), + Id: fmt.Sprintf("%x", truststorage.ChainID(chain)), + Issuer: issuer.String(), + Subject: subject.String(), Validity: Validity{ NotAfter: chain[0].NotAfter, NotBefore: chain[0].NotBefore, @@ -117,7 +117,7 @@ func (s *Server) GetCertificates( func (s *Server) GetCertificate(w http.ResponseWriter, r *http.Request, chainID ChainID) { w.Header().Set("Content-Type", "application/json") - id, err := hex.DecodeString(string(chainID)) + id, err := hex.DecodeString(chainID) if err != nil { Error(w, Problem{ Detail: api.StringRef(err.Error()), @@ -145,9 +145,9 @@ func (s *Server) GetCertificate(w http.ResponseWriter, r *http.Request, chainID result := Chain{ Subject: Certificate{ DistinguishedName: chain[0].Subject.String(), - IsdAs: IsdAs(subject.String()), + IsdAs: subject.String(), SubjectKeyAlgo: chain[0].PublicKeyAlgorithm.String(), - SubjectKeyId: SubjectKeyID(fmt.Sprintf("% X", chain[0].SubjectKeyId)), + SubjectKeyId: fmt.Sprintf("% X", chain[0].SubjectKeyId), Validity: Validity{ NotAfter: chain[0].NotAfter, NotBefore: chain[0].NotBefore, @@ -155,9 +155,9 @@ func (s *Server) GetCertificate(w http.ResponseWriter, r *http.Request, chainID }, Issuer: Certificate{ DistinguishedName: chain[1].Subject.String(), - IsdAs: IsdAs(issuer.String()), + IsdAs: issuer.String(), SubjectKeyAlgo: chain[1].PublicKeyAlgorithm.String(), - SubjectKeyId: SubjectKeyID(fmt.Sprintf("% X", chain[1].SubjectKeyId)), + SubjectKeyId: fmt.Sprintf("% X", chain[1].SubjectKeyId), Validity: Validity{ NotAfter: chain[1].NotAfter, NotBefore: chain[1].NotBefore, @@ -182,7 +182,7 @@ func (s *Server) GetCertificate(w http.ResponseWriter, r *http.Request, chainID func (s *Server) GetCertificateBlob(w http.ResponseWriter, r *http.Request, chainID ChainID) { w.Header().Set("Content-Type", "application/x-pem-file") - id, err := hex.DecodeString(string(chainID)) + id, err := hex.DecodeString(chainID) if err != nil { Error(w, Problem{ Detail: api.StringRef(err.Error()), @@ -298,11 +298,11 @@ func (s *Server) GetTrc(w http.ResponseWriter, r *http.Request, isd int, base in } authASes := make([]IsdAs, 0, len(trc.TRC.AuthoritativeASes)) for _, as := range trc.TRC.AuthoritativeASes { - authASes = append(authASes, IsdAs(addr.MustIAFrom(trc.TRC.ID.ISD, as).String())) + authASes = append(authASes, addr.MustIAFrom(trc.TRC.ID.ISD, as).String()) } coreAses := make([]IsdAs, 0, len(trc.TRC.CoreASes)) for _, as := range trc.TRC.CoreASes { - coreAses = append(coreAses, IsdAs(addr.MustIAFrom(trc.TRC.ID.ISD, as).String())) + coreAses = append(coreAses, addr.MustIAFrom(trc.TRC.ID.ISD, as).String()) } rep := TRC{ AuthoritativeAses: authASes, diff --git a/private/mgmtapi/cppki/api/client.gen.go b/private/mgmtapi/cppki/api/client.gen.go index ea908e4e6..01dc6bb5f 100644 --- a/private/mgmtapi/cppki/api/client.gen.go +++ b/private/mgmtapi/cppki/api/client.gen.go @@ -7,7 +7,7 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/url" "strings" @@ -551,6 +551,7 @@ type GetCertificatesResponse struct { Body []byte HTTPResponse *http.Response JSON200 *[]ChainBrief + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -573,6 +574,7 @@ type GetCertificateResponse struct { Body []byte HTTPResponse *http.Response JSON200 *Chain + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -594,6 +596,7 @@ func (r GetCertificateResponse) StatusCode() int { type GetCertificateBlobResponse struct { Body []byte HTTPResponse *http.Response + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -736,7 +739,7 @@ func (c *ClientWithResponses) GetTrcBlobWithResponse(ctx context.Context, isd in // ParseGetCertificatesResponse parses an HTTP response from a GetCertificatesWithResponse call func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -755,6 +758,13 @@ func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -762,7 +772,7 @@ func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, // ParseGetCertificateResponse parses an HTTP response from a GetCertificateWithResponse call func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -781,6 +791,13 @@ func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, e } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -788,7 +805,7 @@ func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, e // ParseGetCertificateBlobResponse parses an HTTP response from a GetCertificateBlobWithResponse call func ParseGetCertificateBlobResponse(rsp *http.Response) (*GetCertificateBlobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -799,12 +816,22 @@ func ParseGetCertificateBlobResponse(rsp *http.Response) (*GetCertificateBlobRes HTTPResponse: rsp, } + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + return response, nil } // ParseGetTrcsResponse parses an HTTP response from a GetTrcsWithResponse call func ParseGetTrcsResponse(rsp *http.Response) (*GetTrcsResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -837,7 +864,7 @@ func ParseGetTrcsResponse(rsp *http.Response) (*GetTrcsResponse, error) { // ParseGetTrcResponse parses an HTTP response from a GetTrcWithResponse call func ParseGetTrcResponse(rsp *http.Response) (*GetTrcResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -870,7 +897,7 @@ func ParseGetTrcResponse(rsp *http.Response) (*GetTrcResponse, error) { // ParseGetTrcBlobResponse parses an HTTP response from a GetTrcBlobWithResponse call func ParseGetTrcBlobResponse(rsp *http.Response) (*GetTrcBlobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err diff --git a/private/mgmtapi/cppki/api/server.gen.go b/private/mgmtapi/cppki/api/server.gen.go index 06f8fabc4..55f02bc0e 100644 --- a/private/mgmtapi/cppki/api/server.gen.go +++ b/private/mgmtapi/cppki/api/server.gen.go @@ -40,7 +40,7 @@ type ServerInterfaceWrapper struct { ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) } -type MiddlewareFunc func(http.HandlerFunc) http.HandlerFunc +type MiddlewareFunc func(http.Handler) http.Handler // GetCertificates operation middleware func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *http.Request) { @@ -52,9 +52,6 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt var params GetCertificatesParams // ------------- Optional query parameter "isd_as" ------------- - if paramValue := r.URL.Query().Get("isd_as"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "isd_as", r.URL.Query(), ¶ms.IsdAs) if err != nil { @@ -63,9 +60,6 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt } // ------------- Optional query parameter "valid_at" ------------- - if paramValue := r.URL.Query().Get("valid_at"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "valid_at", r.URL.Query(), ¶ms.ValidAt) if err != nil { @@ -74,9 +68,6 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt } // ------------- Optional query parameter "all" ------------- - if paramValue := r.URL.Query().Get("all"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "all", r.URL.Query(), ¶ms.All) if err != nil { @@ -84,15 +75,15 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificates(w, r, params) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetCertificate operation middleware @@ -104,21 +95,21 @@ func (siw *ServerInterfaceWrapper) GetCertificate(w http.ResponseWriter, r *http // ------------- Path parameter "chain-id" ------------- var chainId ChainID - err = runtime.BindStyledParameter("simple", false, "chain-id", chi.URLParam(r, "chain-id"), &chainId) + err = runtime.BindStyledParameterWithLocation("simple", false, "chain-id", runtime.ParamLocationPath, chi.URLParam(r, "chain-id"), &chainId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "chain-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificate(w, r, chainId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetCertificateBlob operation middleware @@ -130,21 +121,21 @@ func (siw *ServerInterfaceWrapper) GetCertificateBlob(w http.ResponseWriter, r * // ------------- Path parameter "chain-id" ------------- var chainId ChainID - err = runtime.BindStyledParameter("simple", false, "chain-id", chi.URLParam(r, "chain-id"), &chainId) + err = runtime.BindStyledParameterWithLocation("simple", false, "chain-id", runtime.ParamLocationPath, chi.URLParam(r, "chain-id"), &chainId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "chain-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificateBlob(w, r, chainId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetTrcs operation middleware @@ -157,9 +148,6 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques var params GetTrcsParams // ------------- Optional query parameter "isd" ------------- - if paramValue := r.URL.Query().Get("isd"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", false, false, "isd", r.URL.Query(), ¶ms.Isd) if err != nil { @@ -168,9 +156,6 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques } // ------------- Optional query parameter "all" ------------- - if paramValue := r.URL.Query().Get("all"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "all", r.URL.Query(), ¶ms.All) if err != nil { @@ -178,15 +163,15 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcs(w, r, params) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetTrc operation middleware @@ -198,7 +183,7 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request // ------------- Path parameter "isd" ------------- var isd int - err = runtime.BindStyledParameter("simple", false, "isd", chi.URLParam(r, "isd"), &isd) + err = runtime.BindStyledParameterWithLocation("simple", false, "isd", runtime.ParamLocationPath, chi.URLParam(r, "isd"), &isd) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "isd", Err: err}) return @@ -207,7 +192,7 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request // ------------- Path parameter "base" ------------- var base int - err = runtime.BindStyledParameter("simple", false, "base", chi.URLParam(r, "base"), &base) + err = runtime.BindStyledParameterWithLocation("simple", false, "base", runtime.ParamLocationPath, chi.URLParam(r, "base"), &base) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "base", Err: err}) return @@ -216,21 +201,21 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request // ------------- Path parameter "serial" ------------- var serial int - err = runtime.BindStyledParameter("simple", false, "serial", chi.URLParam(r, "serial"), &serial) + err = runtime.BindStyledParameterWithLocation("simple", false, "serial", runtime.ParamLocationPath, chi.URLParam(r, "serial"), &serial) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "serial", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrc(w, r, isd, base, serial) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetTrcBlob operation middleware @@ -242,7 +227,7 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req // ------------- Path parameter "isd" ------------- var isd int - err = runtime.BindStyledParameter("simple", false, "isd", chi.URLParam(r, "isd"), &isd) + err = runtime.BindStyledParameterWithLocation("simple", false, "isd", runtime.ParamLocationPath, chi.URLParam(r, "isd"), &isd) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "isd", Err: err}) return @@ -251,7 +236,7 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req // ------------- Path parameter "base" ------------- var base int - err = runtime.BindStyledParameter("simple", false, "base", chi.URLParam(r, "base"), &base) + err = runtime.BindStyledParameterWithLocation("simple", false, "base", runtime.ParamLocationPath, chi.URLParam(r, "base"), &base) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "base", Err: err}) return @@ -260,21 +245,21 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req // ------------- Path parameter "serial" ------------- var serial int - err = runtime.BindStyledParameter("simple", false, "serial", chi.URLParam(r, "serial"), &serial) + err = runtime.BindStyledParameterWithLocation("simple", false, "serial", runtime.ParamLocationPath, chi.URLParam(r, "serial"), &serial) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "serial", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcBlob(w, r, isd, base, serial) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } type UnescapedCookieParamError struct { @@ -290,16 +275,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshalingParamError struct { +type UnmarshallingParamError struct { ParamName string Err error } -func (e *UnmarshalingParamError) Error() string { - return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshallingParamError) Error() string { + return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshalingParamError) Unwrap() error { +func (e *UnmarshallingParamError) Unwrap() error { return e.Err } diff --git a/private/mgmtapi/cppki/api/types.gen.go b/private/mgmtapi/cppki/api/types.gen.go index 28ca0752e..fdb4a005d 100644 --- a/private/mgmtapi/cppki/api/types.gen.go +++ b/private/mgmtapi/cppki/api/types.gen.go @@ -31,37 +31,37 @@ type ChainBrief struct { } // ChainID defines model for ChainID. -type ChainID string +type ChainID = string // IsdAs defines model for IsdAs. -type IsdAs string +type IsdAs = string // Problem defines model for Problem. type Problem struct { - // A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Detail A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Detail *string `json:"detail,omitempty"` - // A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. + // Instance A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. Instance *string `json:"instance,omitempty"` - // The HTTP status code generated by the origin server for this occurrence of the problem. + // Status The HTTP status code generated by the origin server for this occurrence of the problem. Status int `json:"status"` - // A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Title A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Title string `json:"title"` - // A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. + // Type A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. Type *string `json:"type,omitempty"` } // StandardError defines model for StandardError. type StandardError struct { - // Error message + // Error Error message Error string `json:"error"` } // SubjectKeyID defines model for SubjectKeyID. -type SubjectKeyID string +type SubjectKeyID = string // TRC defines model for TRC. type TRC struct { @@ -91,17 +91,17 @@ type Validity struct { } // BadRequest defines model for BadRequest. -type BadRequest StandardError +type BadRequest = StandardError // GetCertificatesParams defines parameters for GetCertificates. type GetCertificatesParams struct { - IsdAs *IsdAs `json:"isd_as,omitempty"` - ValidAt *time.Time `json:"valid_at,omitempty"` - All *bool `json:"all,omitempty"` + IsdAs *IsdAs `form:"isd_as,omitempty" json:"isd_as,omitempty"` + ValidAt *time.Time `form:"valid_at,omitempty" json:"valid_at,omitempty"` + All *bool `form:"all,omitempty" json:"all,omitempty"` } // GetTrcsParams defines parameters for GetTrcs. type GetTrcsParams struct { - Isd *[]int `json:"isd,omitempty"` - All *bool `json:"all,omitempty"` + Isd *[]int `form:"isd,omitempty" json:"isd,omitempty"` + All *bool `form:"all,omitempty" json:"all,omitempty"` } diff --git a/private/mgmtapi/health/api/client.gen.go b/private/mgmtapi/health/api/client.gen.go index 61e9adcfe..d4df7b2bc 100644 --- a/private/mgmtapi/health/api/client.gen.go +++ b/private/mgmtapi/health/api/client.gen.go @@ -7,7 +7,7 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/url" "strings" @@ -210,7 +210,7 @@ func (c *ClientWithResponses) GetHealthWithResponse(ctx context.Context, reqEdit // ParseGetHealthResponse parses an HTTP response from a GetHealthWithResponse call func ParseGetHealthResponse(rsp *http.Response) (*GetHealthResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err diff --git a/private/mgmtapi/health/api/helpers.go b/private/mgmtapi/health/api/helpers.go index 70156a035..0f9cb11b9 100644 --- a/private/mgmtapi/health/api/helpers.go +++ b/private/mgmtapi/health/api/helpers.go @@ -16,13 +16,13 @@ package api // AggregateHealthStatus returns the least healthy status of the input. func AggregateHealthStatus(checksStatus []Status) Status { - lowestStatus := StatusPassing + lowestStatus := Passing for _, checkStatus := range checksStatus { switch checkStatus { - case StatusFailing: - return StatusFailing - case StatusDegraded: - lowestStatus = StatusDegraded + case Failing: + return Failing + case Degraded: + lowestStatus = Degraded } } return lowestStatus diff --git a/private/mgmtapi/health/api/server.gen.go b/private/mgmtapi/health/api/server.gen.go index c8cd05892..f21264e57 100644 --- a/private/mgmtapi/health/api/server.gen.go +++ b/private/mgmtapi/health/api/server.gen.go @@ -24,21 +24,21 @@ type ServerInterfaceWrapper struct { ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) } -type MiddlewareFunc func(http.HandlerFunc) http.HandlerFunc +type MiddlewareFunc func(http.Handler) http.Handler // GetHealth operation middleware func (siw *ServerInterfaceWrapper) GetHealth(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetHealth(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } type UnescapedCookieParamError struct { @@ -54,16 +54,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshalingParamError struct { +type UnmarshallingParamError struct { ParamName string Err error } -func (e *UnmarshalingParamError) Error() string { - return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshallingParamError) Error() string { + return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshalingParamError) Unwrap() error { +func (e *UnmarshallingParamError) Unwrap() error { return e.Err } diff --git a/private/mgmtapi/health/api/types.gen.go b/private/mgmtapi/health/api/types.gen.go index e78a5b199..62dddbfc7 100644 --- a/private/mgmtapi/health/api/types.gen.go +++ b/private/mgmtapi/health/api/types.gen.go @@ -3,43 +3,34 @@ // Code generated by unknown module path version unknown version DO NOT EDIT. package api -import ( - "encoding/json" - "fmt" -) - // Defines values for Status. const ( - StatusDegraded Status = "degraded" - - StatusFailing Status = "failing" - - StatusPassing Status = "passing" + Degraded Status = "degraded" + Failing Status = "failing" + Passing Status = "passing" ) // Check defines model for Check. type Check struct { Data CheckData `json:"data"` - // Additional information. + // Detail Additional information. Detail *string `json:"detail,omitempty"` - // Name of health check. + // Name Name of health check. Name string `json:"name"` - // Reason for check failure. + // Reason Reason for check failure. Reason *string `json:"reason,omitempty"` Status Status `json:"status"` } // CheckData defines model for CheckData. -type CheckData struct { - AdditionalProperties map[string]interface{} `json:"-"` -} +type CheckData map[string]interface{} // Health defines model for Health. type Health struct { - // List of health checks. + // Checks List of health checks. Checks []Check `json:"checks"` Status Status `json:"status"` } @@ -51,7 +42,7 @@ type HealthResponse struct { // StandardError defines model for StandardError. type StandardError struct { - // Error message + // Error Error message Error string `json:"error"` } @@ -59,57 +50,4 @@ type StandardError struct { type Status string // BadRequest defines model for BadRequest. -type BadRequest StandardError - -// Getter for additional properties for CheckData. Returns the specified -// element and whether it was found -func (a CheckData) Get(fieldName string) (value interface{}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for CheckData -func (a *CheckData) Set(fieldName string, value interface{}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]interface{}) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for CheckData to handle AdditionalProperties -func (a *CheckData) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { - var fieldVal interface{} - err := json.Unmarshal(fieldBuf, &fieldVal) - if err != nil { - return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) - } - a.AdditionalProperties[fieldName] = fieldVal - } - } - return nil -} - -// Override default JSON handling for CheckData to handle AdditionalProperties -func (a CheckData) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - for fieldName, field := range a.AdditionalProperties { - object[fieldName], err = json.Marshal(field) - if err != nil { - return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) - } - } - return json.Marshal(object) -} +type BadRequest = StandardError diff --git a/private/mgmtapi/segments/api/api.go b/private/mgmtapi/segments/api/api.go index 216284ef5..2d40f2c04 100644 --- a/private/mgmtapi/segments/api/api.go +++ b/private/mgmtapi/segments/api/api.go @@ -46,14 +46,14 @@ func (s *Server) GetSegments(w http.ResponseWriter, r *http.Request, params GetS q := query.Params{} var errs serrors.List if params.StartIsdAs != nil { - if ia, err := addr.ParseIA(string(*params.StartIsdAs)); err == nil { + if ia, err := addr.ParseIA(*params.StartIsdAs); err == nil { q.StartsAt = []addr.IA{ia} } else { errs = append(errs, serrors.WithCtx(err, "parameter", "start_isd_as")) } } if params.EndIsdAs != nil { - if ia, err := addr.ParseIA(string(*params.EndIsdAs)); err == nil { + if ia, err := addr.ParseIA(*params.EndIsdAs); err == nil { q.EndsAt = []addr.IA{ia} } else { errs = append(errs, serrors.WithCtx(err, "parameter", "end_isd_as")) @@ -82,9 +82,9 @@ func (s *Server) GetSegments(w http.ResponseWriter, r *http.Request, params GetS rep := make([]*SegmentBrief, 0, len(res)) for _, segRes := range res { rep = append(rep, &SegmentBrief{ - Id: SegmentID(SegID(segRes.Seg)), - StartIsdAs: IsdAs(segRes.Seg.FirstIA().String()), - EndIsdAs: IsdAs(segRes.Seg.LastIA().String()), + Id: SegID(segRes.Seg), + StartIsdAs: segRes.Seg.FirstIA().String(), + EndIsdAs: segRes.Seg.LastIA().String(), Length: len(segRes.Seg.ASEntries), }) } @@ -103,7 +103,7 @@ func (s *Server) GetSegments(w http.ResponseWriter, r *http.Request, params GetS // GetSegment gets a segments details specified by its ID. func (s *Server) GetSegment(w http.ResponseWriter, r *http.Request, segmentID SegmentID) { - id, err := hex.DecodeString(string(segmentID)) + id, err := hex.DecodeString(segmentID) if err != nil { Error(w, Problem{ Detail: api.StringRef(err.Error()), @@ -142,16 +142,18 @@ func (s *Server) GetSegment(w http.ResponseWriter, r *http.Request, segmentID Se if i != 0 { hops = append(hops, Hop{ Interface: int(as.HopEntry.HopField.ConsIngress), - IsdAs: IsdAs(as.Local.String())}) + IsdAs: as.Local.String(), + }) } if i != len(segRes.Seg.ASEntries)-1 { hops = append(hops, Hop{ Interface: int(as.HopEntry.HopField.ConsEgress), - IsdAs: IsdAs(as.Local.String())}) + IsdAs: as.Local.String(), + }) } } rep := Segment{ - Id: SegmentID(SegID(segRes.Seg)), + Id: SegID(segRes.Seg), Timestamp: segRes.Seg.Info.Timestamp.UTC(), Expiration: segRes.Seg.MinExpiry().UTC(), LastUpdated: segRes.LastUpdate.UTC(), @@ -175,7 +177,7 @@ func (s *Server) GetSegment(w http.ResponseWriter, r *http.Request, segmentID Se func (s *Server) GetSegmentBlob(w http.ResponseWriter, r *http.Request, segmentID SegmentID) { w.Header().Set("Content-Type", "application/x-pem-file") - id, err := hex.DecodeString(string(segmentID)) + id, err := hex.DecodeString(segmentID) if err != nil { Error(w, Problem{ Detail: api.StringRef(err.Error()), diff --git a/private/mgmtapi/segments/api/client.gen.go b/private/mgmtapi/segments/api/client.gen.go index 8916a43b3..b0f6e2ca3 100644 --- a/private/mgmtapi/segments/api/client.gen.go +++ b/private/mgmtapi/segments/api/client.gen.go @@ -7,7 +7,7 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/url" "strings" @@ -322,6 +322,7 @@ type GetSegmentsResponse struct { Body []byte HTTPResponse *http.Response JSON200 *[]SegmentBrief + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -344,6 +345,7 @@ type GetSegmentResponse struct { Body []byte HTTPResponse *http.Response JSON200 *Segment + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -365,6 +367,7 @@ func (r GetSegmentResponse) StatusCode() int { type GetSegmentBlobResponse struct { Body []byte HTTPResponse *http.Response + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -412,7 +415,7 @@ func (c *ClientWithResponses) GetSegmentBlobWithResponse(ctx context.Context, se // ParseGetSegmentsResponse parses an HTTP response from a GetSegmentsWithResponse call func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -431,6 +434,13 @@ func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -438,7 +448,7 @@ func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) // ParseGetSegmentResponse parses an HTTP response from a GetSegmentWithResponse call func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -457,6 +467,13 @@ func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -464,7 +481,7 @@ func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { // ParseGetSegmentBlobResponse parses an HTTP response from a GetSegmentBlobWithResponse call func ParseGetSegmentBlobResponse(rsp *http.Response) (*GetSegmentBlobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -475,5 +492,15 @@ func ParseGetSegmentBlobResponse(rsp *http.Response) (*GetSegmentBlobResponse, e HTTPResponse: rsp, } + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + return response, nil } diff --git a/private/mgmtapi/segments/api/server.gen.go b/private/mgmtapi/segments/api/server.gen.go index 439c9c0ae..b27cd475d 100644 --- a/private/mgmtapi/segments/api/server.gen.go +++ b/private/mgmtapi/segments/api/server.gen.go @@ -31,7 +31,7 @@ type ServerInterfaceWrapper struct { ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) } -type MiddlewareFunc func(http.HandlerFunc) http.HandlerFunc +type MiddlewareFunc func(http.Handler) http.Handler // GetSegments operation middleware func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Request) { @@ -43,9 +43,6 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re var params GetSegmentsParams // ------------- Optional query parameter "start_isd_as" ------------- - if paramValue := r.URL.Query().Get("start_isd_as"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "start_isd_as", r.URL.Query(), ¶ms.StartIsdAs) if err != nil { @@ -54,9 +51,6 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re } // ------------- Optional query parameter "end_isd_as" ------------- - if paramValue := r.URL.Query().Get("end_isd_as"); paramValue != "" { - - } err = runtime.BindQueryParameter("form", true, false, "end_isd_as", r.URL.Query(), ¶ms.EndIsdAs) if err != nil { @@ -64,15 +58,15 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegments(w, r, params) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetSegment operation middleware @@ -84,21 +78,21 @@ func (siw *ServerInterfaceWrapper) GetSegment(w http.ResponseWriter, r *http.Req // ------------- Path parameter "segment-id" ------------- var segmentId SegmentID - err = runtime.BindStyledParameter("simple", false, "segment-id", chi.URLParam(r, "segment-id"), &segmentId) + err = runtime.BindStyledParameterWithLocation("simple", false, "segment-id", runtime.ParamLocationPath, chi.URLParam(r, "segment-id"), &segmentId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "segment-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegment(w, r, segmentId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetSegmentBlob operation middleware @@ -110,21 +104,21 @@ func (siw *ServerInterfaceWrapper) GetSegmentBlob(w http.ResponseWriter, r *http // ------------- Path parameter "segment-id" ------------- var segmentId SegmentID - err = runtime.BindStyledParameter("simple", false, "segment-id", chi.URLParam(r, "segment-id"), &segmentId) + err = runtime.BindStyledParameterWithLocation("simple", false, "segment-id", runtime.ParamLocationPath, chi.URLParam(r, "segment-id"), &segmentId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "segment-id", Err: err}) return } - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegmentBlob(w, r, segmentId) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } type UnescapedCookieParamError struct { @@ -140,16 +134,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshalingParamError struct { +type UnmarshallingParamError struct { ParamName string Err error } -func (e *UnmarshalingParamError) Error() string { - return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshallingParamError) Error() string { + return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshalingParamError) Unwrap() error { +func (e *UnmarshallingParamError) Unwrap() error { return e.Err } diff --git a/private/mgmtapi/segments/api/types.gen.go b/private/mgmtapi/segments/api/types.gen.go index 1d4b45731..268dd1fc7 100644 --- a/private/mgmtapi/segments/api/types.gen.go +++ b/private/mgmtapi/segments/api/types.gen.go @@ -14,23 +14,23 @@ type Hop struct { } // IsdAs defines model for IsdAs. -type IsdAs string +type IsdAs = string // Problem defines model for Problem. type Problem struct { - // A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Detail A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Detail *string `json:"detail,omitempty"` - // A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. + // Instance A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. Instance *string `json:"instance,omitempty"` - // The HTTP status code generated by the origin server for this occurrence of the problem. + // Status The HTTP status code generated by the origin server for this occurrence of the problem. Status int `json:"status"` - // A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Title A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Title string `json:"title"` - // A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. + // Type A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. Type *string `json:"type,omitempty"` } @@ -48,19 +48,19 @@ type SegmentBrief struct { EndIsdAs IsdAs `json:"end_isd_as"` Id SegmentID `json:"id"` - // Length of the segment. + // Length Length of the segment. Length int `json:"length"` StartIsdAs IsdAs `json:"start_isd_as"` } // SegmentID defines model for SegmentID. -type SegmentID string +type SegmentID = string // GetSegmentsParams defines parameters for GetSegments. type GetSegmentsParams struct { - // Start ISD-AS of segment. - StartIsdAs *IsdAs `json:"start_isd_as,omitempty"` + // StartIsdAs Start ISD-AS of segment. + StartIsdAs *IsdAs `form:"start_isd_as,omitempty" json:"start_isd_as,omitempty"` - // Terminal AS of segment. - EndIsdAs *IsdAs `json:"end_isd_as,omitempty"` + // EndIsdAs Terminal AS of segment. + EndIsdAs *IsdAs `form:"end_isd_as,omitempty" json:"end_isd_as,omitempty"` } diff --git a/router/mgmtapi/api.go b/router/mgmtapi/api.go index f4b6ce5fd..92d969e91 100644 --- a/router/mgmtapi/api.go +++ b/router/mgmtapi/api.go @@ -55,7 +55,7 @@ func (s *Server) SetLogLevel(w http.ResponseWriter, r *http.Request) { func (s *Server) GetInterfaces(w http.ResponseWriter, r *http.Request) { internalInterfaces, err := s.Dataplane.ListInternalInterfaces() if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "error getting internal interface", @@ -65,7 +65,7 @@ func (s *Server) GetInterfaces(w http.ResponseWriter, r *http.Request) { } externalInterfaces, err := s.Dataplane.ListExternalInterfaces() if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "error getting external interfaces", @@ -75,7 +75,7 @@ func (s *Server) GetInterfaces(w http.ResponseWriter, r *http.Request) { } siblingInterfaces, err := s.Dataplane.ListSiblingInterfaces() if err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "error getting sibling interfaces", @@ -106,10 +106,10 @@ func (s *Server) GetInterfaces(w http.ResponseWriter, r *http.Request) { InternalInterface: findInternalInterface(intf.Link.Local.IA), Neighbor: InterfaceNeighbor{ Address: intf.Link.Remote.Addr.String(), - IsdAs: IsdAs(intf.Link.Remote.IA.String()), + IsdAs: intf.Link.Remote.IA.String(), }, Relationship: LinkRelationship(intf.Link.LinkTo.String()), - ScionMtu: ScionMTU(intf.Link.MTU), + ScionMtu: intf.Link.MTU, State: LinkState(intf.State), } @@ -121,10 +121,10 @@ func (s *Server) GetInterfaces(w http.ResponseWriter, r *http.Request) { InterfaceId: int(intf.InterfaceID), InternalInterface: intf.InternalInterface.String(), Neighbor: SiblingNeighbor{ - IsdAs: IsdAs(intf.NeighborIA.String()), + IsdAs: intf.NeighborIA.String(), }, Relationship: LinkRelationship(intf.Relationship.String()), - ScionMtu: ScionMTU(intf.MTU), + ScionMtu: intf.MTU, State: LinkState(intf.State), } @@ -138,7 +138,7 @@ func (s *Server) GetInterfaces(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) enc.SetIndent("", " ") if err := enc.Encode(rep); err != nil { - Error(w, Problem{ + ErrorResponse(w, Problem{ Detail: api.StringRef(err.Error()), Status: http.StatusInternalServerError, Title: "unable to marshal response", @@ -149,7 +149,7 @@ func (s *Server) GetInterfaces(w http.ResponseWriter, r *http.Request) { } // Error creates an detailed error response. -func Error(w http.ResponseWriter, p Problem) { +func ErrorResponse(w http.ResponseWriter, p Problem) { w.Header().Set("Content-Type", "application/problem+json") w.WriteHeader(p.Status) enc := json.NewEncoder(w) diff --git a/router/mgmtapi/client.gen.go b/router/mgmtapi/client.gen.go index 2d60fc169..a9f43f310 100644 --- a/router/mgmtapi/client.gen.go +++ b/router/mgmtapi/client.gen.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -435,6 +434,7 @@ type GetInterfacesResponse struct { Body []byte HTTPResponse *http.Response JSON200 *InterfacesResponse + JSON400 *Problem } // Status returns HTTPResponse.Status @@ -554,7 +554,7 @@ func (c *ClientWithResponses) SetLogLevelWithResponse(ctx context.Context, body // ParseGetConfigResponse parses an HTTP response from a GetConfigWithResponse call func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -580,7 +580,7 @@ func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { // ParseGetInfoResponse parses an HTTP response from a GetInfoWithResponse call func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -606,7 +606,7 @@ func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { // ParseGetInterfacesResponse parses an HTTP response from a GetInterfacesWithResponse call func ParseGetInterfacesResponse(rsp *http.Response) (*GetInterfacesResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -625,6 +625,13 @@ func ParseGetInterfacesResponse(rsp *http.Response) (*GetInterfacesResponse, err } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + } return response, nil @@ -632,7 +639,7 @@ func ParseGetInterfacesResponse(rsp *http.Response) (*GetInterfacesResponse, err // ParseGetLogLevelResponse parses an HTTP response from a GetLogLevelWithResponse call func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err @@ -665,7 +672,7 @@ func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) // ParseSetLogLevelResponse parses an HTTP response from a SetLogLevelWithResponse call func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) + bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err diff --git a/router/mgmtapi/server.gen.go b/router/mgmtapi/server.gen.go index bb66926bb..0743b7dac 100644 --- a/router/mgmtapi/server.gen.go +++ b/router/mgmtapi/server.gen.go @@ -36,81 +36,81 @@ type ServerInterfaceWrapper struct { ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) } -type MiddlewareFunc func(http.HandlerFunc) http.HandlerFunc +type MiddlewareFunc func(http.Handler) http.Handler // GetConfig operation middleware func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetConfig(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetInfo operation middleware func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInfo(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetInterfaces operation middleware func (siw *ServerInterfaceWrapper) GetInterfaces(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInterfaces(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // GetLogLevel operation middleware func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetLogLevel(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } // SetLogLevel operation middleware func (siw *ServerInterfaceWrapper) SetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler = func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetLogLevel(w, r) - } + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler(w, r.WithContext(ctx)) + handler.ServeHTTP(w, r.WithContext(ctx)) } type UnescapedCookieParamError struct { @@ -126,16 +126,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshalingParamError struct { +type UnmarshallingParamError struct { ParamName string Err error } -func (e *UnmarshalingParamError) Error() string { - return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshallingParamError) Error() string { + return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshalingParamError) Unwrap() error { +func (e *UnmarshallingParamError) Unwrap() error { return e.Err } diff --git a/router/mgmtapi/types.gen.go b/router/mgmtapi/types.gen.go index 0e72f6134..322c17b32 100644 --- a/router/mgmtapi/types.gen.go +++ b/router/mgmtapi/types.gen.go @@ -5,43 +5,37 @@ package mgmtapi // Defines values for LinkRelationship. const ( - LinkRelationshipCHILD LinkRelationship = "CHILD" - - LinkRelationshipCORE LinkRelationship = "CORE" - - LinkRelationshipPARENT LinkRelationship = "PARENT" - - LinkRelationshipPEER LinkRelationship = "PEER" + CHILD LinkRelationship = "CHILD" + CORE LinkRelationship = "CORE" + PARENT LinkRelationship = "PARENT" + PEER LinkRelationship = "PEER" ) // Defines values for LinkState. const ( - LinkStateDOWN LinkState = "DOWN" - - LinkStateUP LinkState = "UP" + DOWN LinkState = "DOWN" + UP LinkState = "UP" ) // Defines values for LogLevelLevel. const ( - LogLevelLevelDebug LogLevelLevel = "debug" - - LogLevelLevelError LogLevelLevel = "error" - - LogLevelLevelInfo LogLevelLevel = "info" + Debug LogLevelLevel = "debug" + Error LogLevelLevel = "error" + Info LogLevelLevel = "info" ) // BFD defines model for BFD. type BFD struct { - // The minimum interval between transmission of BFD control packets that the operator desires. This value is advertised to the peer, however the actual interval used is specified by taking the maximum of desired-minimum-tx-interval and the value of the remote required-minimum-receive interval value. + // DesiredMinimumTxInterval The minimum interval between transmission of BFD control packets that the operator desires. This value is advertised to the peer, however the actual interval used is specified by taking the maximum of desired-minimum-tx-interval and the value of the remote required-minimum-receive interval value. DesiredMinimumTxInterval string `json:"desired_minimum_tx_interval"` - // The number of packets that must be missed to declare this session as down. The detection interval for the BFD session is calculated by multiplying the value of the negotiated transmission interval by this value. + // DetectionMultiplier The number of packets that must be missed to declare this session as down. The detection interval for the BFD session is calculated by multiplying the value of the negotiated transmission interval by this value. DetectionMultiplier int `json:"detection_multiplier"` - // Indication of whether BFD is enabled and configured on this interface. + // Enabled Indication of whether BFD is enabled and configured on this interface. Enabled bool `json:"enabled"` - // The minimum interval between received BFD control packets that this system should support. This value is advertised to the remote peer to indicate the maximum frequency (i.e., minimum inter-packet interval) between BFD control packets that is acceptable to the local system. + // RequiredMinimumReceive The minimum interval between received BFD control packets that this system should support. This value is advertised to the remote peer to indicate the maximum frequency (i.e., minimum inter-packet interval) between BFD control packets that is acceptable to the local system. RequiredMinimumReceive string `json:"required_minimum_receive"` } @@ -49,22 +43,22 @@ type BFD struct { type Interface struct { Bfd BFD `json:"bfd"` - // SCION interface identifier. + // InterfaceId SCION interface identifier. InterfaceId int `json:"interface_id"` - // The address of internal SCION interface of the router. + // InternalInterface The address of internal SCION interface of the router. InternalInterface string `json:"internal_interface"` Neighbor InterfaceNeighbor `json:"neighbor"` Relationship LinkRelationship `json:"relationship"` - // The maximum transmission unit in bytes for SCION packets. This represents the protocol data unit (PDU) of the SCION layer and is usually calculated as maximum Ethernet payload - IP Header - UDP Header. + // ScionMtu The maximum transmission unit in bytes for SCION packets. This represents the protocol data unit (PDU) of the SCION layer and is usually calculated as maximum Ethernet payload - IP Header - UDP Header. ScionMtu ScionMTU `json:"scion_mtu"` State LinkState `json:"state"` } // InterfaceNeighbor defines model for InterfaceNeighbor. type InterfaceNeighbor struct { - // UDP/IP underlay address of the SCION Interface. + // Address UDP/IP underlay address of the SCION Interface. Address string `json:"address"` IsdAs IsdAs `json:"isd_as"` } @@ -76,7 +70,7 @@ type InterfacesResponse struct { } // IsdAs defines model for IsdAs. -type IsdAs string +type IsdAs = string // LinkRelationship defines model for LinkRelationship. type LinkRelationship string @@ -86,45 +80,45 @@ type LinkState string // LogLevel defines model for LogLevel. type LogLevel struct { - // Logging level + // Level Logging level Level LogLevelLevel `json:"level"` } -// Logging level +// LogLevelLevel Logging level type LogLevelLevel string // Problem defines model for Problem. type Problem struct { - // A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Detail A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Detail *string `json:"detail,omitempty"` - // A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. + // Instance A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. Instance *string `json:"instance,omitempty"` - // The HTTP status code generated by the origin server for this occurrence of the problem. + // Status The HTTP status code generated by the origin server for this occurrence of the problem. Status int `json:"status"` - // A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + // Title A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. Title string `json:"title"` - // A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. + // Type A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. Type *string `json:"type,omitempty"` } -// The maximum transmission unit in bytes for SCION packets. This represents the protocol data unit (PDU) of the SCION layer and is usually calculated as maximum Ethernet payload - IP Header - UDP Header. -type ScionMTU int +// ScionMTU The maximum transmission unit in bytes for SCION packets. This represents the protocol data unit (PDU) of the SCION layer and is usually calculated as maximum Ethernet payload - IP Header - UDP Header. +type ScionMTU = int // SiblingInterface defines model for SiblingInterface. type SiblingInterface struct { - // SCION interface identifier. + // InterfaceId SCION interface identifier. InterfaceId int `json:"interface_id"` - // Internal address of the local router. + // InternalInterface Internal address of the local router. InternalInterface string `json:"internal_interface"` Neighbor SiblingNeighbor `json:"neighbor"` Relationship LinkRelationship `json:"relationship"` - // The maximum transmission unit in bytes for SCION packets. This represents the protocol data unit (PDU) of the SCION layer and is usually calculated as maximum Ethernet payload - IP Header - UDP Header. + // ScionMtu The maximum transmission unit in bytes for SCION packets. This represents the protocol data unit (PDU) of the SCION layer and is usually calculated as maximum Ethernet payload - IP Header - UDP Header. ScionMtu ScionMTU `json:"scion_mtu"` State LinkState `json:"state"` } @@ -136,15 +130,12 @@ type SiblingNeighbor struct { // StandardError defines model for StandardError. type StandardError struct { - // Error message + // Error Error message Error string `json:"error"` } // BadRequest defines model for BadRequest. -type BadRequest StandardError - -// SetLogLevelJSONBody defines parameters for SetLogLevel. -type SetLogLevelJSONBody LogLevel +type BadRequest = StandardError // SetLogLevelJSONRequestBody defines body for SetLogLevel for application/json ContentType. -type SetLogLevelJSONRequestBody SetLogLevelJSONBody +type SetLogLevelJSONRequestBody = LogLevel diff --git a/rules_openapi/internal/bundle.bzl b/rules_openapi/internal/bundle.bzl index efd2efd98..6021eb1c8 100644 --- a/rules_openapi/internal/bundle.bzl +++ b/rules_openapi/internal/bundle.bzl @@ -35,7 +35,7 @@ openapi_bundle = rule( mandatory = True, ), "_openapi_cli": attr.label( - default = "@rules_openapi_npm//@redocly/openapi-cli/bin:openapi", + default = "@rules_openapi_npm//@redocly/cli/bin:openapi", executable = True, cfg = "target", ), diff --git a/rules_openapi/tools/package.json b/rules_openapi/tools/package.json index 80e3a8570..dc8fd2a9d 100644 --- a/rules_openapi/tools/package.json +++ b/rules_openapi/tools/package.json @@ -1,7 +1,9 @@ { "dependencies": { - "@redocly/openapi-cli": "^1.0.0-beta.59", - "@stoplight/spectral-cli": "^6.0.0", - "redoc-cli": "^0.12.3" + "@redocly/cli": "^1.0.0-beta.123", + "@stoplight/spectral-cli": "^6.6.0", + "lodash.get": "^4.4.2", + "lodash.set": "^4.3.2", + "redoc-cli": "^0.13.2" } } diff --git a/rules_openapi/tools/yarn.lock b/rules_openapi/tools/yarn.lock index dc8443b78..9fb2a2d8a 100644 --- a/rules_openapi/tools/yarn.lock +++ b/rules_openapi/tools/yarn.lock @@ -2,10 +2,12 @@ # yarn lockfile v1 -"@asyncapi/specs@^3.2.0": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@asyncapi/specs/-/specs-3.2.1.tgz#b0dfe054154d3a6bb89f2ba23ea6379a754875d0" - integrity sha512-FO+EteK+Gk3zwumrBw6frpp9cJ4oQL5++hBBpfM81w16e9KaiA4sKrzvQsvVjifoZZHNvVEX4D2zoz9i8CLccQ== +"@asyncapi/specs@^4.1.0": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@asyncapi/specs/-/specs-4.1.1.tgz#3cb9fa9e1e7cf2c205d22ff4fba7ddbc41bcfb62" + integrity sha512-CtJdKTQnzX3UwHVBgwrzLIwmnlxl1VKsLNG9ORgdUoD7BFB1fEh9hjdCD3Qh3eHhvlfizLtlFlGet1yQBSi1mg== + dependencies: + "@types/json-schema" "^7.0.11" "@babel/code-frame@^7.18.6": version "7.18.6" @@ -14,13 +16,14 @@ dependencies: "@babel/highlight" "^7.18.6" -"@babel/generator@^7.19.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.3.tgz#d7f4d1300485b4547cb6f94b27d10d237b42bf59" - integrity sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ== +"@babel/generator@^7.21.0": + version "7.21.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" + integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== dependencies: - "@babel/types" "^7.19.3" + "@babel/types" "^7.21.0" "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" "@babel/helper-annotate-as-pure@^7.16.0": @@ -35,13 +38,13 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== -"@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== +"@babel/helper-function-name@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" + integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" + "@babel/template" "^7.20.7" + "@babel/types" "^7.21.0" "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" @@ -64,10 +67,10 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-string-parser@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" - integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" @@ -83,52 +86,59 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.18.10", "@babel/parser@^7.19.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.3.tgz#8dd36d17c53ff347f9e55c328710321b49479a9a" - integrity sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ== +"@babel/parser@^7.20.7", "@babel/parser@^7.21.0": + version "7.21.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.1.tgz#a8f81ee2fe872af23faea4b17a08fcc869de7bcc" + integrity sha512-JzhBFpkuhBNYUY7qs+wTzNmyCWUHEaAFpQQD2YfU1rPL38/L43Wvid0fFkiOCnHvsGncRZgEPyGnltABLcVDTg== -"@babel/runtime@^7.14.0", "@babel/runtime@^7.17.8": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" - integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== +"@babel/runtime@^7.17.8": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" + integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== dependencies: - regenerator-runtime "^0.13.4" + regenerator-runtime "^0.13.11" -"@babel/template@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== +"@babel/template@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" "@babel/traverse@^7.4.5": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.3.tgz#3a3c5348d4988ba60884e8494b0592b2f15a04b4" - integrity sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.0.tgz#0e1807abd5db98e6a19c204b80ed1e3f5bca0edc" + integrity sha512-Xdt2P1H4LKTO8ApPfnO1KmzYMFpp7D/EinoXzLYN/cHcBNrVCAkAtGUcXnHXrl/VGktureU6fkQrHSBE2URfoA== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.3" + "@babel/generator" "^7.21.0" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" + "@babel/helper-function-name" "^7.21.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.19.3" - "@babel/types" "^7.19.3" + "@babel/parser" "^7.21.0" + "@babel/types" "^7.21.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.19.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.3.tgz#fc420e6bbe54880bce6779ffaf315f5e43ec9624" - integrity sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw== +"@babel/types@^7.18.6", "@babel/types@^7.20.7", "@babel/types@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.0.tgz#1da00d89c2f18b226c9207d96edbeb79316a1819" + integrity sha512-uR7NWq2VNFnDi7EYqiRz2Jv/VQIu38tu64Zy8TX2nQFQ6etJ9V/Rr2msW8BS132mum2rL645qpDrLtAJtVpuow== dependencies: - "@babel/helper-string-parser" "^7.18.10" + "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@emotion/is-prop-valid@^0.8.8": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" + integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== + dependencies: + "@emotion/memoize" "0.7.4" + "@emotion/is-prop-valid@^1.1.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz#7f2d35c97891669f7e276eb71c83376a5dc44c83" @@ -136,6 +146,11 @@ dependencies: "@emotion/memoize" "^0.8.0" +"@emotion/memoize@0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" + integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== + "@emotion/memoize@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" @@ -152,9 +167,9 @@ integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== "@exodus/schemasafe@^1.0.0-rc.2": - version "1.0.0-rc.7" - resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.0.0-rc.7.tgz#aded6839c2369883dafa46608a135c82b42ed76b" - integrity sha512-+1mBLsa+vvlV0lwEAP1hwgmOPkjMnoJ8hyCMfCCJga0sVDwDzrPJjnxZwdDaUmOh/vbFHQGBTk+FxsVjoI/CjQ== + version "1.0.0-rc.9" + resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.0.0-rc.9.tgz#56b9c6df627190f2dcda15f81f25d68826d9be4d" + integrity sha512-dGGHpb61hLwifAu7sotuHFDBw6GTdpG8aKC0fsK17EuTzMRvUrH7lEAr6LTJ+sx3AZYed9yZ77rltVDHyg2hRg== "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" @@ -165,7 +180,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@^3.0.3": +"@jridgewell/resolve-uri@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== @@ -175,18 +190,18 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.15" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" - integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" "@jsep-plugin/regex@^1.0.1": version "1.0.3" @@ -219,7 +234,7 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@redocly/ajv@^8.11.0", "@redocly/ajv@^8.6.4": +"@redocly/ajv@^8.11.0": version "8.11.0" resolved "https://registry.yarnpkg.com/@redocly/ajv/-/ajv-8.11.0.tgz#2fad322888dc0113af026e08fceb3e71aae495ae" integrity sha512-9GWx27t7xWhDIR02PA18nzBdLcKQRgc46xNQvjFkrYk4UOmvKhJ/dawwiX0cCOeetN5LcaaiqQbVOWYK62SGHw== @@ -229,43 +244,31 @@ require-from-string "^2.0.2" uri-js "^4.2.2" -"@redocly/openapi-cli@^1.0.0-beta.59": - version "1.0.0-beta.95" - resolved "https://registry.yarnpkg.com/@redocly/openapi-cli/-/openapi-cli-1.0.0-beta.95.tgz#c4cc68f0e8a81bb87d054062300e9c204c04ca00" - integrity sha512-pl/OAeKh/psk6kF9SZjRieJK15T6T5GYcKVeBHvT7vtuhIBRBkrLC3bf3BhiMQx49BdSTB7Tk4/0LFPy0zr1MA== +"@redocly/cli@^1.0.0-beta.123": + version "1.0.0-beta.123" + resolved "https://registry.yarnpkg.com/@redocly/cli/-/cli-1.0.0-beta.123.tgz#b69f221c6bf73f38b09e96f8df27d0fbdfc47e6d" + integrity sha512-aTlqewdXj0LXjh38xJ5lfa380Nyu/cq9+CmfUKXk95/5BDkbJvOjTInxndsjB/KgKbOJlx0vnEoktms0aDhtNw== dependencies: - "@redocly/openapi-core" "1.0.0-beta.95" - "@types/node" "^14.11.8" + "@redocly/openapi-core" "1.0.0-beta.123" assert-node-version "^1.0.3" chokidar "^3.5.1" colorette "^1.2.0" glob "^7.1.6" glob-promise "^3.4.0" handlebars "^4.7.6" + mobx "^6.3.2" portfinder "^1.0.26" + react "^17.0.1" + react-dom "^17.0.1" + redoc "~2.0.0" simple-websocket "^9.0.0" + styled-components "5.3.3" yargs "17.0.1" -"@redocly/openapi-core@1.0.0-beta.95": - version "1.0.0-beta.95" - resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.0.0-beta.95.tgz#23f92f524080c080060204f9103380de28ecae50" - integrity sha512-7Nnc4Obp/1lbrjNjD33oOnZCuoJa8awhBCEyyayPWGQFp1SkhjpZJnfnKkFuYbQzMjTIAvEeSp9DOQK/E0fgEA== - dependencies: - "@redocly/ajv" "^8.6.4" - "@types/node" "^14.11.8" - colorette "^1.2.0" - js-levenshtein "^1.1.6" - js-yaml "^4.1.0" - lodash.isequal "^4.5.0" - minimatch "^3.0.4" - node-fetch "^2.6.1" - pluralize "^8.0.0" - yaml-ast-parser "0.0.43" - -"@redocly/openapi-core@^1.0.0-beta.50": - version "1.0.0-beta.110" - resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.0.0-beta.110.tgz#8c822e188c30e274f8f2e1078b92c19843777581" - integrity sha512-i+7NkKB7I4eEjkAXH02FHxAIcn08S2rUFA9PND4EQHMYw6kxkXQ+hPnBVwaXCzonauqO1CTwVqb8ZcTeKcvtgw== +"@redocly/openapi-core@1.0.0-beta.123", "@redocly/openapi-core@^1.0.0-beta.104": + version "1.0.0-beta.123" + resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.0.0-beta.123.tgz#0c29ae9fabe5f143f571caf608a7d025f41125db" + integrity sha512-W6MbUWpb/VaV+Kf0c3jmMIJw3WwwF7iK5nAfcOS+ZwrlbxtIl37+1hEydFlJ209vCR9HL12PaMwdh2Vpihj6Jw== dependencies: "@redocly/ajv" "^8.11.0" "@types/node" "^14.11.8" @@ -278,24 +281,6 @@ pluralize "^8.0.0" yaml-ast-parser "0.0.43" -"@redocly/react-dropdown-aria@^2.0.11": - version "2.0.12" - resolved "https://registry.yarnpkg.com/@redocly/react-dropdown-aria/-/react-dropdown-aria-2.0.12.tgz#2e3af2b1b8e9123487109400d6117f0d4a8445a6" - integrity sha512-feQEZlyBvQsbT/fvpJ4jJ5OLGaUPpnskHYDsY8DGpPymN+HUeDQrqkBEbbKRwMKidFTI2cxk2kJNNTnvdS9jyw== - -"@rollup/plugin-commonjs@^20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-20.0.0.tgz#3246872dcbcb18a54aaa6277a8c7d7f1b155b745" - integrity sha512-5K0g5W2Ol8hAcTHqcTBHiA7M58tfmYi1o9KxeJuuRNpGaTa5iLjcyemBitCBcKXaHamOBBEH2dGom6v6Unmqjg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - commondir "^1.0.1" - estree-walker "^2.0.1" - glob "^7.1.6" - is-reference "^1.2.1" - magic-string "^0.25.7" - resolve "^1.17.0" - "@rollup/plugin-commonjs@~22.0.2": version "22.0.2" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz#ee8ca8415cda30d383b4096aad5222435b4b69b6" @@ -318,6 +303,11 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + "@stoplight/better-ajv-errors@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.3.tgz#d74a5c4da5d786c17188d7f4edec505f089885fa" @@ -334,27 +324,10 @@ node-fetch "^2.6.0" tslib "^1.14.1" -"@stoplight/json-ref-resolver@3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.3.tgz#243bc8f6b8f7a5f8b141e2296fd11fb634bfc3ff" - integrity sha512-SgoKXwVnlpIZUyAFX4W79eeuTWvXmNlMfICZixL16GZXnkjcW+uZnfmAU0ZIjcnaTgaI4mjfxn8LAP2KR6Cr0A== - dependencies: - "@stoplight/json" "^3.17.0" - "@stoplight/path" "^1.3.2" - "@stoplight/types" "^12.3.0" - "@types/urijs" "^1.19.16" - dependency-graph "~0.11.0" - fast-memoize "^2.5.2" - immer "^9.0.6" - lodash.get "^4.4.2" - lodash.set "^4.3.2" - tslib "^2.3.1" - urijs "^1.19.6" - -"@stoplight/json-ref-resolver@~3.1.4": - version "3.1.4" - resolved "https://registry.yarnpkg.com/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.4.tgz#f54c00c44f0963d2c60233eeebf0d533cdfb5d8b" - integrity sha512-842JVmMsi++qpDuIX+JpQvK7YY8FXEZZb+/z4xuRfStOAVEryJT/tbgGOWxniSdxEl9Eni5D/I2afMyy6BuiNw== +"@stoplight/json-ref-resolver@~3.1.4", "@stoplight/json-ref-resolver@~3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.5.tgz#e4454a69027559ef3f7272941e99310a19dc8fdf" + integrity sha512-uaKLITor7UF+JBtI84zs3aOWM0L79zp7w9TrBTwPtx5SLbaQQ4HadDKgX5yhFOLMApLdhwhiftF4c0GFanOxGg== dependencies: "@stoplight/json" "^3.17.0" "@stoplight/path" "^1.3.2" @@ -367,21 +340,10 @@ tslib "^2.3.1" urijs "^1.19.11" -"@stoplight/json@3.17.0": - version "3.17.0" - resolved "https://registry.yarnpkg.com/@stoplight/json/-/json-3.17.0.tgz#9d864b63b9c6398c7cecae1340225b15953cac74" - integrity sha512-WW0z2bb0D4t8FTl+zNTCu46J8lEOsrUhBPgwEYQ3Ri2Y0MiRE4U1/9ZV8Ki+pIJznZgY9i42bbFwOBxyZn5/6w== - dependencies: - "@stoplight/ordered-object-literal" "^1.0.2" - "@stoplight/types" "^12.3.0" - jsonc-parser "~2.2.1" - lodash "^4.17.21" - safe-stable-stringify "^1.1" - "@stoplight/json@^3.17.0", "@stoplight/json@^3.17.1", "@stoplight/json@~3.20.1": - version "3.20.1" - resolved "https://registry.yarnpkg.com/@stoplight/json/-/json-3.20.1.tgz#a500c5a0ef3232ec3b2fd36c4456b28085d919ae" - integrity sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg== + version "3.20.2" + resolved "https://registry.yarnpkg.com/@stoplight/json/-/json-3.20.2.tgz#466ba5c6381cfd141f1726439442fbd579804c8e" + integrity sha512-e3Eb/DdLSpJVAsxAG1jKSnl4TVZLl2pH8KsJBWKf5GPCeI58Eo0ZpRTX3HcZ0gBaHWH6CnEHJkCRCONhoFbDIA== dependencies: "@stoplight/ordered-object-literal" "^1.0.3" "@stoplight/path" "^1.3.2" @@ -390,7 +352,7 @@ lodash "^4.17.21" safe-stable-stringify "^1.1" -"@stoplight/ordered-object-literal@^1.0.1", "@stoplight/ordered-object-literal@^1.0.2", "@stoplight/ordered-object-literal@^1.0.3", "@stoplight/ordered-object-literal@~1.0.4": +"@stoplight/ordered-object-literal@^1.0.1", "@stoplight/ordered-object-literal@^1.0.3", "@stoplight/ordered-object-literal@~1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@stoplight/ordered-object-literal/-/ordered-object-literal-1.0.4.tgz#c8bb2698ab229f31e31a16dd1852c867c1f2f2ed" integrity sha512-OF8uib1jjDs5/cCU+iOVy+GJjU3X7vk/qJIkIJFqwmlJKrrtijFmqwbu8XToXrwTYLQTP+Hebws5gtZEmk9jag== @@ -400,22 +362,21 @@ resolved "https://registry.yarnpkg.com/@stoplight/path/-/path-1.3.2.tgz#96e591496b72fde0f0cdae01a61d64f065bd9ede" integrity sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ== -"@stoplight/spectral-cli@^6.0.0": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-cli/-/spectral-cli-6.5.1.tgz#f75d538b01b988259a1971a18bb1f35ad99d4ca6" - integrity sha512-+qpwsDG2jQ4ULQmegBWonI3UnF6tUh351WDnV1GU8acl8eaeKbS+ZUNBgoP2f9tnMTfITdctVRFEGC3D6P7f9g== +"@stoplight/spectral-cli@^6.6.0": + version "6.6.0" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-cli/-/spectral-cli-6.6.0.tgz#6a8cb630bb14408c9ace955ad51fb05049db0fba" + integrity sha512-z46fnrvraaWMio8Y9RYYkLO+XdmtxOWpy5qNJF3CsmWua0FZ4iOTryb5Cm3GkB0wEtqxNUCBUHvoo4hS6Noyqg== dependencies: - "@rollup/plugin-commonjs" "^20.0.0" - "@stoplight/json" "3.17.0" + "@stoplight/json" "~3.20.1" "@stoplight/path" "1.3.2" - "@stoplight/spectral-core" "^1.5.1" - "@stoplight/spectral-parsers" "^1.0.1" - "@stoplight/spectral-ref-resolver" "1.0.1" - "@stoplight/spectral-ruleset-bundler" "^1.0.0" - "@stoplight/spectral-ruleset-migrator" "^1.5.0" + "@stoplight/spectral-core" "^1.15.1" + "@stoplight/spectral-parsers" "^1.0.2" + "@stoplight/spectral-ref-resolver" "1.0.2" + "@stoplight/spectral-ruleset-bundler" "^1.4.0" + "@stoplight/spectral-ruleset-migrator" "^1.9.0" "@stoplight/spectral-rulesets" ">=1" - "@stoplight/spectral-runtime" "^1.1.0" - "@stoplight/types" "12.3.0" + "@stoplight/spectral-runtime" "^1.1.2" + "@stoplight/types" "^13.6.0" chalk "4.1.2" cliui "7.0.4" eol "0.9.1" @@ -429,10 +390,10 @@ tslib "^2.3.0" yargs "17.3.1" -"@stoplight/spectral-core@>=1", "@stoplight/spectral-core@^1.5.1", "@stoplight/spectral-core@^1.7.0", "@stoplight/spectral-core@^1.8.0", "@stoplight/spectral-core@^1.8.1": - version "1.14.2" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-core/-/spectral-core-1.14.2.tgz#db48c1197e3870508d157c677496a314111c8689" - integrity sha512-W2Z31lasEICpZS50STFskOdkn4g0Va81XA1A88LIj9mvlctDFf4BfpjLgIjKkI4f2DEK5C4j3COcbbzV8y5Xig== +"@stoplight/spectral-core@>=1", "@stoplight/spectral-core@^1.15.1", "@stoplight/spectral-core@^1.7.0", "@stoplight/spectral-core@^1.8.0", "@stoplight/spectral-core@^1.8.1": + version "1.16.1" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-core/-/spectral-core-1.16.1.tgz#a4af80c021c0be0c52b92cc7acbdacb97919ea20" + integrity sha512-zPTM/OpjUySMRLPx6ZYy9Gtw+Rkuwg1/gQTKWta+AaJjVTHrNznYQ05gFLYjWwD/LGJMdjwE2IMi7T+Ntef+kw== dependencies: "@stoplight/better-ajv-errors" "1.0.3" "@stoplight/json" "~3.20.1" @@ -446,7 +407,6 @@ ajv "^8.6.0" ajv-errors "~3.0.0" ajv-formats "~2.1.0" - blueimp-md5 "2.18.0" es-aggregate-error "^1.0.7" jsonpath-plus "7.1.0" lodash "~4.17.21" @@ -457,10 +417,10 @@ simple-eval "1.0.0" tslib "^2.3.0" -"@stoplight/spectral-formats@>=1", "@stoplight/spectral-formats@^1.0.0", "@stoplight/spectral-formats@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-formats/-/spectral-formats-1.4.0.tgz#104e49f305914f1645496fe7ea3848a416fec5b3" - integrity sha512-j9VQukDzgqDSi26rK9LqsbXrqtkeIsPSPgEf5/sxRsmeF2bwWUhSjYXgYin4flSZ7owFZjZWQ3o0Qq3iApi2JQ== +"@stoplight/spectral-formats@>=1", "@stoplight/spectral-formats@^1.0.0", "@stoplight/spectral-formats@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-formats/-/spectral-formats-1.5.0.tgz#222dd1e1302c54ba3219b8223b299d9515fed3e3" + integrity sha512-VskkdU3qBSvI1dfJ79ysjvTssfNlbA6wrf/XkXK6iTyjfIVqOAWVtjypTb2U95tN/X8IjIBBhNWtZ4tNVZilrA== dependencies: "@stoplight/json" "^3.17.0" "@stoplight/spectral-core" "^1.8.0" @@ -468,9 +428,9 @@ tslib "^2.3.1" "@stoplight/spectral-functions@>=1", "@stoplight/spectral-functions@^1.0.0", "@stoplight/spectral-functions@^1.5.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-functions/-/spectral-functions-1.7.1.tgz#48b9d4a1598614a6d52ce56feca92e9412e1dc04" - integrity sha512-UWeUrxc1pu45ZNYKtK3OloMpkUNTPqwpmjbGUn4oEnbqrLEYu/B2oOg66EtGcadOBEsdOb7f5vaPlhUNNrpEpQ== + version "1.7.2" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-functions/-/spectral-functions-1.7.2.tgz#96ddc5dc2b093fba41a902a0ef374300f861f58f" + integrity sha512-f+61/FtIkQeIo+a269CeaeqjpyRsgDyIk6DGr7iS4hyuk1PPk7Uf6MNRDs9FEIBh7CpdEJ+HSHbMLwgpymWTIw== dependencies: "@stoplight/better-ajv-errors" "1.0.3" "@stoplight/json" "^3.17.1" @@ -484,7 +444,7 @@ lodash "~4.17.21" tslib "^2.3.0" -"@stoplight/spectral-parsers@>=1", "@stoplight/spectral-parsers@^1.0.0", "@stoplight/spectral-parsers@^1.0.1": +"@stoplight/spectral-parsers@>=1", "@stoplight/spectral-parsers@^1.0.0", "@stoplight/spectral-parsers@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@stoplight/spectral-parsers/-/spectral-parsers-1.0.2.tgz#2411ff5499ad351414ed8e0ea32f1f24efebb49c" integrity sha512-ZQXknJ+BM5Re4Opj4cgVlHgG2qyOk/wznKJq3Vf1qsBEg2CNzN0pJmSB0deRqW0kArqm44qpb8c+cz3F2rgMtw== @@ -494,32 +454,32 @@ "@stoplight/yaml" "~4.2.3" tslib "^2.3.1" -"@stoplight/spectral-ref-resolver@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.1.tgz#884c936a3478380767bdb762fe911cc8cb59a7b3" - integrity sha512-0tY7nTOccvTsa3c4QbSWfJ8wGfPO1RXvmKnmBjuyLfoTMNuhkHPII9gKhCjygsshzsBLxs2IyRHZYhWYVnEbCA== +"@stoplight/spectral-ref-resolver@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.2.tgz#acae9511e17a4da97ecca48c005a4475d24fe76b" + integrity sha512-ah6NIB/O1EdEaEu89So3LmtbKRXPVnSElgQ7oBRE9S4/VOedSqyXn+qqMd40tGnO2CsKgZaFUYXdSEHOshpHYw== dependencies: "@stoplight/json-ref-readers" "1.2.2" - "@stoplight/json-ref-resolver" "3.1.3" - "@stoplight/spectral-runtime" "^1.0.0" + "@stoplight/json-ref-resolver" "~3.1.4" + "@stoplight/spectral-runtime" "^1.1.2" dependency-graph "0.11.0" tslib "^2.3.1" "@stoplight/spectral-ref-resolver@>=1", "@stoplight/spectral-ref-resolver@^1.0.0": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.2.tgz#acae9511e17a4da97ecca48c005a4475d24fe76b" - integrity sha512-ah6NIB/O1EdEaEu89So3LmtbKRXPVnSElgQ7oBRE9S4/VOedSqyXn+qqMd40tGnO2CsKgZaFUYXdSEHOshpHYw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.3.tgz#6754f212c27723af7a438129d47f941184a21edd" + integrity sha512-pj+bH4SH8hcWlnV787WD7P0/En7LA3EfZMvG1JUGMW/7bFd9AaZZXNkh5j0ve8qnPlwP8F4SH/2Cnr1tXOXCVw== dependencies: "@stoplight/json-ref-readers" "1.2.2" - "@stoplight/json-ref-resolver" "~3.1.4" + "@stoplight/json-ref-resolver" "~3.1.5" "@stoplight/spectral-runtime" "^1.1.2" dependency-graph "0.11.0" tslib "^2.3.1" -"@stoplight/spectral-ruleset-bundler@^1.0.0": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.3.2.tgz#528e848e30a9e86e493bd088046c7745f091bc3a" - integrity sha512-sy7mHVBwmo5/8dUlnWiel2UND1Mnu3x+okBAgLmkGcIpXz74rMmVY3h5vT6rjxw65WZ3/c3mtm1dRQuSe+q5fw== +"@stoplight/spectral-ruleset-bundler@^1.4.0": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.5.1.tgz#52031f9e2b118a24bd0f0f66c30fe8b1afec7e0b" + integrity sha512-gvlBXkyxLBNdslN/5HEYvCqMr0dvKQwJbbJCKbOvvRTZhhPVzmLb7yavWXjOnRhYn6IAhGAs7u4yhxn7cX/FtQ== dependencies: "@rollup/plugin-commonjs" "~22.0.2" "@stoplight/path" "1.3.2" @@ -538,10 +498,10 @@ tslib "^2.3.1" validate-npm-package-name "3.0.0" -"@stoplight/spectral-ruleset-migrator@^1.5.0", "@stoplight/spectral-ruleset-migrator@^1.7.4": - version "1.7.4" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.7.4.tgz#d94d0877fb6d4a58addc8a2a36833f800d19b364" - integrity sha512-QySMWSvGUC5D8cNDvXhrXEY0a4DB5hewHwjxXbwlH51fVNiVKJ4+KcaCW3s2yAT4T1p6/ij8NkLX9T81D4vSCg== +"@stoplight/spectral-ruleset-migrator@^1.7.4", "@stoplight/spectral-ruleset-migrator@^1.9.0": + version "1.9.2" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.9.2.tgz#6865273880cbee6b79f68b452cc0632e0205496b" + integrity sha512-FbXsPFt+nikggCF1x+kfaNXpE7Ol/0Um1eR0S1/mNyf/L5R0RBnyqZLvJwC6cU6O49CLAjYy7fCbxgrjNcZvbg== dependencies: "@stoplight/json" "~3.20.1" "@stoplight/ordered-object-literal" "~1.0.4" @@ -559,15 +519,15 @@ validate-npm-package-name "3.0.0" "@stoplight/spectral-rulesets@>=1": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-rulesets/-/spectral-rulesets-1.14.0.tgz#9e4684ef12f9cf1f8d952d2f03cb59a266a72d72" - integrity sha512-yE4V7GYXfcr7QC15clsOTUmecsZqU1upcgvoU8RFJ/yToAsky74EhY+weV9ecfUWrwuamdiTy3MafrsWaywiuA== + version "1.15.0" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-rulesets/-/spectral-rulesets-1.15.0.tgz#df0322b725fd3d244662b7cd72431d17f32b83dd" + integrity sha512-xgltt54aQPSKKAxPZ2oCA25X/xmDPVCV1e4qxqH5bw/t7LvDWVusBFUrtcl/5HAJIIgkpxOKXKEc2XRC0ea8HQ== dependencies: - "@asyncapi/specs" "^3.2.0" + "@asyncapi/specs" "^4.1.0" "@stoplight/better-ajv-errors" "1.0.3" "@stoplight/json" "^3.17.0" "@stoplight/spectral-core" "^1.8.1" - "@stoplight/spectral-formats" "^1.4.0" + "@stoplight/spectral-formats" "^1.5.0" "@stoplight/spectral-functions" "^1.5.1" "@stoplight/spectral-runtime" "^1.1.1" "@stoplight/types" "^13.6.0" @@ -591,14 +551,6 @@ node-fetch "^2.6.7" tslib "^2.3.1" -"@stoplight/types@12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-12.3.0.tgz#ac71d295319f26abb279e3d89d1c1774857d20b4" - integrity sha512-hgzUR1z5BlYvIzUeFK5pjs5JXSvEutA9Pww31+dVicBlunsG1iXopDx/cvfBY7rHOrgtZDuvyeK4seqkwAZ6Cg== - dependencies: - "@types/json-schema" "^7.0.4" - utility-types "^3.10.0" - "@stoplight/types@^12.3.0": version "12.5.0" resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-12.5.0.tgz#ebbeeb8c874de30e4cd9a1a2a6c8d6062c155da0" @@ -608,9 +560,9 @@ utility-types "^3.10.0" "@stoplight/types@^12.3.0 || ^13.0.0", "@stoplight/types@^13.0.0", "@stoplight/types@^13.6.0": - version "13.7.0" - resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-13.7.0.tgz#717d9e3ef068e8f143d045e9bc89b97da06933c4" - integrity sha512-7ePIccfTxjEhruv8VrkDv5whP5qd9ijRzAWEbjYpUYnDfaqPTfq8/wMMjMCAKIecboxsAVD9LZy/3puXddGsDQ== + version "13.9.1" + resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-13.9.1.tgz#adaa19a3d7f8182cd7de65c592bea170f1a8c22e" + integrity sha512-IiInrb/xux6Xf+IQW6I8crbsoxLtNa1mDGQyUDbd6Tyfb9fXAGjIaA1Yb5JXNR3ChLypmd3ROUHEUNAanegGVw== dependencies: "@types/json-schema" "^7.0.4" utility-types "^3.10.0" @@ -638,6 +590,13 @@ "@stoplight/yaml-ast-parser" "0.0.48" tslib "^2.2.0" +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -661,11 +620,11 @@ integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== "@types/glob@*": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.0.0.tgz#321607e9cbaec54f687a0792b2d1d370739455d2" - integrity sha512-l6NQsDDyQUVeoTynNpC9uRvCUint/gSUXQA2euwmTuWGvPY5LSDUu6tkCtJB2SvGQlJQzLaKqcGZP4//7EDveA== + version "8.1.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" + integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== dependencies: - "@types/minimatch" "*" + "@types/minimatch" "^5.1.2" "@types/node" "*" "@types/json-schema@^7.0.11", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.7": @@ -673,27 +632,22 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== -"@types/minimatch@*": +"@types/minimatch@^5.1.2": version "5.1.2" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== "@types/node@*": - version "18.8.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.8.2.tgz#17d42c6322d917764dd3d2d3a10d7884925de067" - integrity sha512-cRMwIgdDN43GO4xMWAfJAecYn8wV4JbsOGHNfNUIDiuYkUYAR5ec4Rj7IO2SAhFPEfpPtLtUTbbny/TCT7aDwA== + version "18.14.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.0.tgz#94c47b9217bbac49d4a67a967fdcdeed89ebb7d0" + integrity sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A== "@types/node@^14.11.8": - version "14.18.31" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.31.tgz#4b873dea3122e71af4f77e65ec5841397ff254d3" - integrity sha512-vQAnaReSQkEDa8uwAyQby8bYGKu84R/deEc6mg5T8fX6gzCn8QW6rziSgsti1fNvsrswKUKPnVTi7uoB+u62Mw== + version "14.18.36" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.36.tgz#c414052cb9d43fab67d679d5f3c641be911f5835" + integrity sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ== -"@types/node@^15.6.1": - version "15.14.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-15.14.9.tgz#bc43c990c3c9be7281868bbc7b8fdd6e2b57adfa" - integrity sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A== - -"@types/urijs@^1.19.16", "@types/urijs@^1.19.19": +"@types/urijs@^1.19.19": version "1.19.19" resolved "https://registry.yarnpkg.com/@types/urijs/-/urijs-1.19.19.tgz#2789369799907fc11e2bc6e3a00f6478c2281b95" integrity sha512-FDJNkyhmKLw7uEvTxx5tSXfPeQpO0iy73Ry+PmYZJvQy0QIWX8a7kJ4kLWRf+EbTPJEPDSgPXHaM7pzr5lmvCg== @@ -711,9 +665,9 @@ acorn-walk@^8.2.0: integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== acorn@^8.7.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== agent-base@6, agent-base@^6.0.0, agent-base@^6.0.2: version "6.0.2" @@ -740,15 +694,22 @@ ajv-formats@~2.1.0: ajv "^8.0.0" ajv@^8.0.0, ajv@^8.6.0, ajv@^8.6.3, ajv@^8.8.2: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" - integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" uri-js "^4.2.2" +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -769,9 +730,9 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: color-convert "^2.0.1" anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -829,9 +790,9 @@ ast-types@^0.13.2: tslib "^2.0.1" astring@^1.7.5, astring@^1.8.1: - version "1.8.3" - resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.3.tgz#1a0ae738c7cc558f8e5ddc8e3120636f5cebcb85" - integrity sha512-sRpyiNrx2dEYIMmUXprS8nlpRg2Drs8m9ElX9vVEXaCB4XEAJhKfs7IcX0IwShjuOAjLR6wzIrgoptz1n19i1A== + version "1.8.4" + resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.4.tgz#6d4c5d8de7be2ead9e4a3cc0e2efb8d759378904" + integrity sha512-97a+l2LBU3Op3bBQEff79i/E4jMD2ZLFD8rHx9B6mXyB2uQwhJQYfiDqUwtfjF4QA1F2qs//N6Cw8LetMbQjcw== async@^2.6.4: version "2.6.4" @@ -840,6 +801,11 @@ async@^2.6.4: dependencies: lodash "^4.17.14" +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + "babel-plugin-styled-components@>= 1.12.0": version "2.0.7" resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz#c81ef34b713f9da2b7d3f5550df0d1e19e798086" @@ -871,11 +837,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -blueimp-md5@2.18.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.18.0.tgz#1152be1335f0c6b3911ed9e36db54f3e6ac52935" - integrity sha512-vE52okJvzsVWhcgUHOv+69OG3Mdg151xyn41aVQN/5W5S+S43qZhxECtYLAEHMSFWX6Mv5IZrzj3T5+JqXfj5Q== - bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -886,6 +847,20 @@ bn.js@^5.0.0, bn.js@^5.1.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +boxen@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1003,6 +978,19 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -1012,16 +1000,21 @@ call-bind@^1.0.0, call-bind@^1.0.2: get-intrinsic "^1.0.2" call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha512-wCyFsDQkKPwwF8BDwOiWNx/9K45L/hvggQiDbve+viMNMQnWhrlYIuBk09offfwCRtCO9P6XwUttufzU11WCVw== + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" + integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== camelize@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" - integrity sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg== + version "1.0.1" + resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" + integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== -chalk@4.1.2: +chalk@4.1.2, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1053,6 +1046,11 @@ chokidar@^3.5.1: optionalDependencies: fsevents "~2.3.2" +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -1066,6 +1064,11 @@ classnames@^2.3.1: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + cliui@7.0.4, cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -1084,6 +1087,13 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" +clone-response@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== + dependencies: + mimic-response "^1.0.0" + clsx@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" @@ -1128,6 +1138,18 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" @@ -1191,15 +1213,20 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + css-color-keywords@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg== css-to-react-native@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756" - integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ== + version "3.2.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32" + integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ== dependencies: camelize "^1.0.0" css-color-keywords "^1.0.0" @@ -1234,15 +1261,32 @@ decko@^1.2.0: resolved "https://registry.yarnpkg.com/decko/-/decko-1.2.0.tgz#fd43c735e967b8013306884a56fbe665996b6817" integrity sha512-m8FnyHXV1QX+S1cl+KPFDIl6NMkxtKsy6+U/aYyjrOqWMuwAwYWu7ePqrsUHtDR5Y8Yk2pi/KIDSgF+vT4cPOQ== +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== + dependencies: + mimic-response "^1.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== dependencies: has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -1290,9 +1334,21 @@ domain-browser@^1.1.1: integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== dompurify@^2.2.8: - version "2.4.0" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.0.tgz#c9c88390f024c2823332615c9e20a453cf3825dd" - integrity sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA== + version "2.4.4" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.4.tgz#c17803931dd524e1b68e0e940a84567f9498f4bd" + integrity sha512-1e2SpqHiRx4DPvmRuXU5J0di3iQACwJM+mFGE2HAkkK7Tbnfk9WcghcAmyWc9CRrjyRRUpmuhPUH6LphQQR3EQ== + +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + dependencies: + is-obj "^2.0.0" + +duplexer3@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" + integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== elliptic@^6.5.3: version "6.5.4" @@ -1312,54 +1368,79 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + eol@0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== -es-abstract@^1.19.0, es-abstract@^1.19.5: - version "1.20.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.3.tgz#90b143ff7aedc8b3d189bcfac7f1e3e3f81e9da1" - integrity sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw== +es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.21.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.1.tgz#e6105a099967c08377830a0c9cb589d570dd86c6" + integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== dependencies: + available-typed-arrays "^1.0.5" call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" function-bind "^1.1.1" function.prototype.name "^1.1.5" get-intrinsic "^1.1.3" get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" has "^1.0.3" has-property-descriptors "^1.0.0" + has-proto "^1.0.1" has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.6" + internal-slot "^1.0.4" + is-array-buffer "^3.0.1" + is-callable "^1.2.7" is-negative-zero "^2.0.2" is-regex "^1.1.4" is-shared-array-buffer "^1.0.2" is-string "^1.0.7" + is-typed-array "^1.1.10" is-weakref "^1.0.2" object-inspect "^1.12.2" object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.4.3" safe-regex-test "^1.0.0" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" es-aggregate-error@^1.0.7: - version "1.0.8" - resolved "https://registry.yarnpkg.com/es-aggregate-error/-/es-aggregate-error-1.0.8.tgz#bc9475174f5c8012b7f7c39d2af415b72ef1e89e" - integrity sha512-AKUb5MKLWMozPlFRHOKqWD7yta5uaEhH21qwtnf6FlKjNjTJOoqFi0/G14+FfSkIQhhu6X68Af4xgRC6y8qG4A== + version "1.0.9" + resolved "https://registry.yarnpkg.com/es-aggregate-error/-/es-aggregate-error-1.0.9.tgz#b50925cdf78c8a634bd766704f6f7825902be3d9" + integrity sha512-fvnX40sb538wdU6r4s35cq4EY6Lr09Upj40BEVem4LEsuW8XgQep9yD5Q1U2KftokNp1rWODFJ2qwZSsAjFpbg== dependencies: define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" function-bind "^1.1.1" functions-have-names "^1.2.3" - get-intrinsic "^1.1.1" - globalthis "^1.0.2" + get-intrinsic "^1.1.3" + globalthis "^1.0.3" has-property-descriptors "^1.0.0" +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -1379,6 +1460,11 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1481,9 +1567,9 @@ fast-safe-stringify@^2.0.7: integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== dependencies: reusify "^1.0.4" @@ -1499,6 +1585,13 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + foreach@^2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.6.tgz#87bcc8a1a0e74000ff2bf9802110708cfb02eb6e" @@ -1556,10 +1649,10 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== dependencies: function-bind "^1.1.1" has "^1.0.3" @@ -1573,6 +1666,20 @@ get-source@^2.0.12: data-uri-to-buffer "^2.0.0" source-map "^0.6.1" +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -1619,19 +1726,50 @@ glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" +global-dirs@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" + integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== + dependencies: + ini "2.0.0" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globalthis@^1.0.2: +globalthis@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== dependencies: define-properties "^1.1.3" -graceful-fs@^4.1.6, graceful-fs@^4.2.0: +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -1670,6 +1808,11 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" @@ -1682,6 +1825,11 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -1722,6 +1870,11 @@ hoist-non-react-statics@^3.0.0: dependencies: react-is "^16.7.0" +http-cache-semantics@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -1773,9 +1926,19 @@ ieee754@^1.1.4: integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== immer@^9.0.6: - version "9.0.15" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc" - integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ== + version "9.0.19" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.19.tgz#67fb97310555690b5f9cd8380d38fc0aabb6b38b" + integrity sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ== + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== inflight@^1.0.4: version "1.0.6" @@ -1800,12 +1963,22 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== +ini@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" + integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +internal-slot@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== dependencies: - get-intrinsic "^1.1.0" + get-intrinsic "^1.2.0" has "^1.0.3" side-channel "^1.0.4" @@ -1819,6 +1992,15 @@ ip@^2.0.0: resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== +is-array-buffer@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz#deb1db4fcae48308d54ef2442706c0393997052a" + integrity sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-typed-array "^1.1.10" + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -1841,15 +2023,22 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-callable@^1.1.4, is-callable@^1.2.6: +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-core-module@^2.9.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" - integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== dependencies: has "^1.0.3" @@ -1877,11 +2066,24 @@ is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-installed-globally@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" + integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== + dependencies: + global-dirs "^3.0.0" + is-path-inside "^3.0.2" + is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-npm@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" + integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== + is-number-object@^1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" @@ -1894,6 +2096,16 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-reference@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" @@ -1930,6 +2142,22 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -1937,6 +2165,11 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -1970,16 +2203,21 @@ js-yaml@^4.1.0: argparse "^2.0.1" jsep@^1.1.2, jsep@^1.2.0: - version "1.3.7" - resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.3.7.tgz#fee6a03ea2bbf61ae5264313a18231e02ab612b3" - integrity sha512-NFbZTr1t13fPKw53swmZFKwBkEDWDnno7uLJk+a+Rw9tGDTkGgnGdZJ8A/o3gR1+XaAXmSsbpfIBIBgqRBZWDA== + version "1.3.8" + resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.3.8.tgz#facb6eb908d085d71d950bd2b24b757c7b8a46d7" + integrity sha512-qofGylTGgYj9gZFsHuyWAN4jr35eJ66qJCK4eKDnldohuUoQFbU3iZn2zjvEbd9wOAhP9Wx5DsAAduTyE1PSWQ== jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -json-pointer@0.6.2, json-pointer@^0.6.1: +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== + +json-pointer@0.6.2, json-pointer@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/json-pointer/-/json-pointer-0.6.2.tgz#f97bd7550be5e9ea901f8c9264c9d436a22a93cd" integrity sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw== @@ -2018,6 +2256,20 @@ jsonpointer@^5.0.0: resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +latest-version@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -2063,6 +2315,16 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -2070,6 +2332,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + lunr@^2.3.9: version "2.3.9" resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" @@ -2082,15 +2351,22 @@ magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + mark.js@^8.11.1: version "8.11.1" resolved "https://registry.yarnpkg.com/mark.js/-/mark.js-8.11.1.tgz#180f1f9ebef8b0e638e4166ad52db879beb2ffc5" integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== -marked@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e" - integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg== +marked@^4.0.15: + version "4.2.12" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.2.12.tgz#d69a64e21d71b06250da995dcd065c11083bebb5" + integrity sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw== md5.js@^1.3.4: version "1.3.5" @@ -2101,11 +2377,6 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -memoize-one@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" - integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== - merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -2127,6 +2398,11 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -2137,7 +2413,7 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@3.1.2, minimatch@^3.0.4, minimatch@^3.1.1: +minimatch@3.1.2, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -2145,16 +2421,16 @@ minimatch@3.1.2, minimatch@^3.0.4, minimatch@^3.1.1: brace-expansion "^1.1.7" minimatch@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7" - integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg== + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== dependencies: brace-expansion "^2.0.1" -minimist@^1.2.5, minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== mkdirp@^0.5.6: version "0.5.6" @@ -2174,16 +2450,16 @@ mobx-react-lite@^3.4.0: integrity sha512-bRuZp3C0itgLKHu/VNxi66DN/XVkQG7xtoBVWxpvC5FhAqbOCP21+nPhULjnzEqd7xBMybp6KwytdUpZKEgpIQ== mobx-react@^7.2.0: - version "7.5.3" - resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-7.5.3.tgz#74b1c148d2f2a1affab3153ea570ab52c7eff70c" - integrity sha512-+ltotliKt4Bjn3d8taZH/VFAcRUbaASvsM8/QSvmHXcZ++RZwaFtjl9JkIosy1byaJGEDS3EFFx2InRm2VaSUw== + version "7.6.0" + resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-7.6.0.tgz#ebf0456728a9bd2e5c24fdcf9b36e285a222a7d6" + integrity sha512-+HQUNuh7AoQ9ZnU6c4rvbiVVl+wEkb9WqYsVDzGLng+Dqj1XntHu79PvEWKtSMoMj67vFp/ZPXcElosuJO8ckA== dependencies: mobx-react-lite "^3.4.0" mobx@^6.3.2: - version "6.6.2" - resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.6.2.tgz#9d9102a0e337e3fc09cb2d8ca0c6f00b61270d5a" - integrity sha512-IOpS0bf3+hXIhDIy+CmlNMBfFpAbHS0aVHcNC+xH/TFYEKIIVDKNYRh9eKlXuVfJ1iRKAp0cRVmO145CyJAMVQ== + version "6.8.0" + resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.8.0.tgz#59051755fdb5c8a9f3f2e0a9b6abaf86bab7f843" + integrity sha512-+o/DrHa4zykFMSKfS8Z+CPSEg5LW9tSNGTuN8o6MF1GKxlfkSHSeJn5UtgxvPkGgaouplnrLXCF+duAsmm6FHQ== ms@2.1.2: version "2.1.2" @@ -2226,9 +2502,9 @@ node-fetch-h2@^2.3.0: http2-client "^1.2.5" node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== dependencies: whatwg-url "^5.0.0" @@ -2273,6 +2549,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + oas-kit-common@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/oas-kit-common/-/oas-kit-common-1.0.8.tgz#6d8cacf6e9097967a4c7ea8bcbcbd77018e1f535" @@ -2325,9 +2606,9 @@ object-assign@^4.1.1: integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.12.2, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== object-keys@^1.1.1: version "1.1.1" @@ -2344,17 +2625,17 @@ object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" -once@^1.3.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" -openapi-sampler@^1.0.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/openapi-sampler/-/openapi-sampler-1.3.0.tgz#5b99ceb4156b00d2aa3f860e52ccb768a5695793" - integrity sha512-2QfjK1oM9Sv0q82Ae1RrUe3yfFmAyjF548+6eAeb+h/cL1Uj51TW4UezraBEvwEdzoBgfo4AaTLVFGTKj+yYDw== +openapi-sampler@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/openapi-sampler/-/openapi-sampler-1.3.1.tgz#eebb2a1048f830cc277398bc8022b415f887e859" + integrity sha512-Ert9mvc2tLPmmInwSyGZS+v4Ogu9/YoZuq9oP3EdUklg2cad6+IGndP9yqJJwbgdXwZibiq5fpv6vYujchdJFg== dependencies: "@types/json-schema" "^7.0.7" json-pointer "0.6.2" @@ -2376,6 +2657,11 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + pac-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz#b718f76475a6a5415c2efbe256c1c971c84f635e" @@ -2400,6 +2686,16 @@ pac-resolver@^5.0.0: ip "^1.1.5" netmask "^2.0.2" +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" @@ -2447,7 +2743,7 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -perfect-scrollbar@^1.5.1: +perfect-scrollbar@^1.5.5: version "1.5.5" resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz#41a211a2fb52a7191eff301432134ea47052b27f" integrity sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g== @@ -2493,12 +2789,17 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== + printable-characters@^1.0.42: version "1.0.42" resolved "https://registry.yarnpkg.com/printable-characters/-/printable-characters-1.0.42.tgz#3f18e977a9bd8eb37fcc4ff5659d7be90868b3d8" integrity sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ== -prismjs@^1.24.1: +prismjs@^1.27.0: version "1.29.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== @@ -2553,6 +2854,14 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" @@ -2564,9 +2873,16 @@ punycode@^1.2.4: integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +pupa@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" + integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== + dependencies: + escape-goat "^2.0.0" querystring-es3@^0.2.0: version "0.2.1" @@ -2599,15 +2915,25 @@ randomfill@^1.0.3: safe-buffer "^5.1.0" raw-body@^2.2.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" http-errors "2.0.0" iconv-lite "0.4.24" unpipe "1.0.0" +rc@1.2.8, rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-dom@^17.0.1: version "17.0.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" @@ -2677,10 +3003,10 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -redoc-cli@^0.12.3: - version "0.12.3" - resolved "https://registry.yarnpkg.com/redoc-cli/-/redoc-cli-0.12.3.tgz#54e5ccc3aae05cb6bcb78ee45493c15e6c0a627c" - integrity sha512-qTBaEfwVqCvqLbuloZ9sMBQA49WfMOQrLVBGiVyT7pNMAjosQCpMyFESqQL8WqVxDzV2olPCZ1L2rG9cuDGOsA== +redoc-cli@^0.13.2: + version "0.13.20" + resolved "https://registry.yarnpkg.com/redoc-cli/-/redoc-cli-0.13.20.tgz#66a238f8dd6b6509e5475df81dddaa75ed9d1465" + integrity sha512-mmaJFyaAS+kzh2GwX7pi1x4K/zbQynJFv9S4mp3Ra5Rw611XxKjWmuVF3ccPV+TAGEe0rU3fYkMuOQg1pA8RWw== dependencies: chokidar "^3.5.1" handlebars "^4.7.7" @@ -2690,38 +3016,64 @@ redoc-cli@^0.12.3: node-libs-browser "^2.2.1" react "^17.0.1" react-dom "^17.0.1" - redoc "2.0.0-rc.56" + redoc "2.0.0-rc.77" styled-components "^5.3.0" - yargs "^17.0.1" + update-notifier "^5.0.1" + yargs "^17.3.1" -redoc@2.0.0-rc.56: - version "2.0.0-rc.56" - resolved "https://registry.yarnpkg.com/redoc/-/redoc-2.0.0-rc.56.tgz#d0fc05149d4801aa6ddf430af223070f04dce596" - integrity sha512-ir2TtQ2d/1FqZWIoLmUZ3qvAAnO6jg8dt0SV75TanmfCXpEABcElXWH3mtUf6qKlvgDVt40diDCVuSvyPPxkAw== +redoc@2.0.0-rc.77: + version "2.0.0-rc.77" + resolved "https://registry.yarnpkg.com/redoc/-/redoc-2.0.0-rc.77.tgz#bb1f46bfb65e08b59a58e23f2d7b272cf1f5a3cb" + integrity sha512-hiCMNSEl6R9vDkiVBMJSKxyT+wLY0qZdw+UZuOHWDCFm3uV0SELwTUU+spVBFCdzM4fdxjCnvsY2vX6cjcJNNg== dependencies: - "@babel/runtime" "^7.14.0" - "@redocly/openapi-core" "^1.0.0-beta.50" - "@redocly/react-dropdown-aria" "^2.0.11" - "@types/node" "^15.6.1" + "@redocly/openapi-core" "^1.0.0-beta.104" classnames "^2.3.1" decko "^1.2.0" dompurify "^2.2.8" eventemitter3 "^4.0.7" - json-pointer "^0.6.1" + json-pointer "^0.6.2" lunr "^2.3.9" mark.js "^8.11.1" - marked "^0.7.0" - memoize-one "^5.2.1" + marked "^4.0.15" mobx-react "^7.2.0" - openapi-sampler "^1.0.1" + openapi-sampler "^1.3.0" path-browserify "^1.0.1" - perfect-scrollbar "^1.5.1" + perfect-scrollbar "^1.5.5" polished "^4.1.3" - prismjs "^1.24.1" + prismjs "^1.27.0" prop-types "^15.7.2" react-tabs "^3.2.2" slugify "~1.4.7" stickyfill "^1.1.1" + style-loader "^3.3.1" + swagger2openapi "^7.0.6" + url-template "^2.0.8" + +redoc@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/redoc/-/redoc-2.0.0.tgz#8b3047ca75b84d31558c6c92da7f84affef35c3e" + integrity sha512-rU8iLdAkT89ywOkYk66Mr+IofqaMASlRvTew0dJvopCORMIPUcPMxjlJbJNC6wsn2vvMnpUFLQ/0ISDWn9BWag== + dependencies: + "@redocly/openapi-core" "^1.0.0-beta.104" + classnames "^2.3.1" + decko "^1.2.0" + dompurify "^2.2.8" + eventemitter3 "^4.0.7" + json-pointer "^0.6.2" + lunr "^2.3.9" + mark.js "^8.11.1" + marked "^4.0.15" + mobx-react "^7.2.0" + openapi-sampler "^1.3.0" + path-browserify "^1.0.1" + perfect-scrollbar "^1.5.5" + polished "^4.1.3" + prismjs "^1.27.0" + prop-types "^15.7.2" + react-tabs "^3.2.2" + slugify "~1.4.7" + stickyfill "^1.1.1" + style-loader "^3.3.1" swagger2openapi "^7.0.6" url-template "^2.0.8" @@ -2730,10 +3082,10 @@ reftools@^1.1.9: resolved "https://registry.yarnpkg.com/reftools/-/reftools-1.1.9.tgz#e16e19f662ccd4648605312c06d34e5da3a2b77e" integrity sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w== -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== regexp.prototype.flags@^1.4.3: version "1.4.3" @@ -2744,6 +3096,20 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" +registry-auth-token@^4.0.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" + integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== + dependencies: + rc "1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -2768,6 +3134,13 @@ resolve@^1.17.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== + dependencies: + lowercase-keys "^1.0.0" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -2832,11 +3205,30 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" + integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== + dependencies: + semver "^6.3.0" + semver@^5.0.3: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.4: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + setimmediate@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -2913,6 +3305,11 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + simple-eval@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/simple-eval/-/simple-eval-1.0.0.tgz#7ba8e6049840690b2d4e356ed01f13209e03aad1" @@ -3005,7 +3402,7 @@ stream-http@^2.7.2: to-arraybuffer "^1.0.0" xtend "^4.0.0" -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -3014,23 +3411,23 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" @@ -3058,6 +3455,32 @@ strip-ansi@6.0, strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +style-loader@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" + integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== + +styled-components@5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.3.tgz#312a3d9a549f4708f0fb0edc829eb34bde032743" + integrity sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/traverse" "^7.4.5" + "@emotion/is-prop-valid" "^0.8.8" + "@emotion/stylis" "^0.8.4" + "@emotion/unitless" "^0.7.4" + babel-plugin-styled-components ">= 1.12.0" + css-to-react-native "^3.0.0" + hoist-non-react-statics "^3.0.0" + shallowequal "^1.1.0" + supports-color "^5.5.0" + styled-components@^5.3.0: version "5.3.6" resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.6.tgz#27753c8c27c650bee9358e343fc927966bfd00d1" @@ -3132,6 +3555,11 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3155,9 +3583,9 @@ tslib@^1.14.1: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.0.1, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + version "2.5.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" + integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== tty-browserify@0.0.0: version "0.0.0" @@ -3171,10 +3599,31 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + uglify-js@^3.1.4: - version "3.17.3" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.3.tgz#f0feedf019c4510f164099e8d7e72ff2d7304377" - integrity sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg== + version "3.17.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== unbox-primitive@^1.0.2: version "1.0.2" @@ -3186,6 +3635,13 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -3196,6 +3652,26 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +update-notifier@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" + integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== + dependencies: + boxen "^5.0.0" + chalk "^4.1.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.4.0" + is-npm "^5.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.1.0" + pupa "^2.1.1" + semver "^7.3.4" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -3203,11 +3679,18 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urijs@^1.19.11, urijs@^1.19.6: +urijs@^1.19.11: version "1.19.11" resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== + dependencies: + prepend-http "^2.0.0" + url-template@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" @@ -3258,9 +3741,9 @@ vm-browserify@^1.0.1: integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== vm2@^3.9.8: - version "3.9.11" - resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.11.tgz#a880f510a606481719ec3f9803b940c5805a06fe" - integrity sha512-PFG8iJRSjvvBdisowQ7iVF580DXb1uCIiGaXgm7tynMR1uTBlv7UJlB1zdv5KJ+Tmq1f0Upnj3fayoEOPpCBKg== + version "3.9.14" + resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.14.tgz#964042b474cf1e6e4f475a39144773cdb9deb734" + integrity sha512-HgvPHYHeQy8+QhzlFryvSteA4uQLBCOub02mgqdR+0bN/akRZ48TGB1v0aCv7ksyc0HXx16AZtMHKS38alc6TA== dependencies: acorn "^8.7.0" acorn-walk "^8.2.0" @@ -3289,6 +3772,25 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -3313,11 +3815,26 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + ws@^7.4.2: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + xregexp@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" @@ -3338,6 +3855,11 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yaml-ast-parser@0.0.43: version "0.0.43" resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" @@ -3353,7 +3875,7 @@ yargs-parser@^20.2.2: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-parser@^21.0.0: +yargs-parser@^21.0.0, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== @@ -3384,10 +3906,10 @@ yargs@17.3.1: y18n "^5.0.5" yargs-parser "^21.0.0" -yargs@^17.0.1: - version "17.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.0.tgz#e134900fc1f218bc230192bdec06a0a5f973e46c" - integrity sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g== +yargs@^17.0.1, yargs@^17.3.1: + version "17.7.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" + integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== dependencies: cliui "^8.0.1" escalade "^3.1.1" @@ -3395,4 +3917,4 @@ yargs@^17.0.1: require-directory "^2.1.1" string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^21.0.0" + yargs-parser "^21.1.1" diff --git a/spec/ca.gen.yml b/spec/ca.gen.yml index 2accff3c5..c334eda9f 100644 --- a/spec/ca.gen.yml +++ b/spec/ca.gen.yml @@ -20,18 +20,14 @@ paths: - name: isd-number in: path required: true - description: >- - ISD number of the Autonomous System requesting the certificate chain - renewal. + description: ISD number of the Autonomous System requesting the certificate chain renewal. schema: type: integer example: 1 - name: as-number in: path required: true - description: >- - AS Number of the Autonomous System requesting the certificate chain - renewal. + description: AS Number of the Autonomous System requesting the certificate chain renewal. schema: $ref: '#/components/schemas/AS' post: @@ -202,43 +198,27 @@ components: type: type: string format: uri-reference - description: >- - A URI reference that uniquely identifies the problem type in the - context of the provided API. + description: A URI reference that uniquely identifies the problem type in the context of the provided API. default: about:blank example: /problem/policy-violation title: type: string - description: >- - A short summary of the problem type. Written in English and readable - for engineers, usually not suited for non technical stakeholders and - not localized. + description: A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Policy Violation status: type: integer - description: >- - The HTTP status code generated by the server for this occurrence of - the problem. + description: The HTTP status code generated by the server for this occurrence of the problem. minimum: 100 maximum: 599 example: 400 detail: type: string - description: >- - A human readable explanation specific to this occurrence of the - problem that is helpful to locate the problem and give advice on how - to proceed. Written in English and readable for engineers, usually - not suited for non technical stakeholders and not localized. - example: >- - The CSR sent violates the certification policy of the issuing CA. - Field CN must not contain underscore characters. + description: A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. + example: The CSR sent violates the certification policy of the issuing CA. Field CN must not contain underscore characters. instance: type: string format: uri-reference - description: >- - A URI reference that identifies the specific occurrence of the - problem, e.g. by adding a fragment identifier or sub-path to the - problem type. + description: A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. example: /problem/policy-violation#cn-malformed correlation_id: type: string @@ -267,8 +247,7 @@ components: access_token: type: string description: The encoded JWT token - example: >- - eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c token_type: description: Type of returned access token. Currently always Bearer. type: string @@ -297,13 +276,10 @@ components: - status responses: 400-BadRequest: - description: > + description: | The request is malformed or lacks required information. - - Incomplete request structure (protocol error) - - - Request information violates PKI policy requirements (application - error) + - Request information violates PKI policy requirements (application error) content: application/problem+json: schema: @@ -319,11 +295,9 @@ components: schema: $ref: '#/components/schemas/Problem' 404-NotFound: - description: > + description: | The requested resource does not exist. - - - Request acts on an unknown resource like an unknown AS (application - error) + - Request acts on an unknown resource like an unknown AS (application error) content: application/problem+json: schema: diff --git a/spec/control.gen.yml b/spec/control.gen.yml index 1306f9e7f..9eea747f1 100644 --- a/spec/control.gen.yml +++ b/spec/control.gen.yml @@ -26,10 +26,7 @@ paths: tags: - segment summary: List the SCION path segments - description: >- - List the SCION path segments that are known to the service. The results - can be filtered by the start and end AS of the segment. Inspect the - individual segments for a more detailed view. + description: List the SCION path segments that are known to the service. The results can be filtered by the start and end AS of the segment. Inspect the individual segments for a more detailed view. operationId: get-segments parameters: - in: query @@ -121,9 +118,7 @@ paths: get: tags: - cppki - summary: >- - Prints information about the AS Certificate used to sign the - control-plane message. + summary: Prints information about the AS Certificate used to sign the control-plane message. operationId: get-signer responses: '200': @@ -176,10 +171,7 @@ paths: tags: - cppki summary: List the TRCs - description: >- - List the latest SCION Trust Root Configurations for each ISD that are - known to the control service. The result can be filtered by ISD. - Optionally, all TRCs can be requested instead of only the latest ones. + description: List the latest SCION Trust Root Configurations for each ISD that are known to the control service. The result can be filtered by ISD. Optionally, all TRCs can be requested instead of only the latest ones. operationId: get-trcs parameters: - in: query @@ -465,25 +457,17 @@ paths: tags: - beacon summary: List the SCION beacons - description: >- - List the SCION beacons that are known to the control service. The - results can be filtered by the start AS, ingress interface and usage of - the beacon. By default, all unexpired beacons are returned. This - behavior can be changed with the `all` and `valid_at` parameters. + description: List the SCION beacons that are known to the control service. The results can be filtered by the start AS, ingress interface and usage of the beacon. By default, all unexpired beacons are returned. This behavior can be changed with the `all` and `valid_at` parameters. operationId: get-beacons parameters: - in: query - description: >- - Start ISD-AS of beacons. The address can include wildcards (0) both - for the ISD and AS identifier. + description: Start ISD-AS of beacons. The address can include wildcards (0) both for the ISD and AS identifier. name: start_isd_as example: 1-ff00:0:110 schema: $ref: '#/components/schemas/IsdAs' - in: query - description: >- - Minimum allowed usages of the returned beacons. Only beacons that - are allowed in all the usages in the list will be returned. + description: Minimum allowed usages of the returned beacons. Only beacons that are allowed in all the usages in the list will be returned. name: usages example: - up_registration @@ -499,9 +483,7 @@ paths: minimum: 0 maximum: 65535 - in: query - description: >- - Timestamp at which returned beacons are valid. If unset then the - current datetime is used. This only has an effect if `all=false`. + description: Timestamp at which returned beacons are valid. If unset then the current datetime is used. This only has an effect if `all=false`. name: valid_at example: '2021-11-25T12:20:50.52Z' schema: @@ -520,9 +502,7 @@ paths: default: false type: boolean - in: query - description: >- - Attribute by which results are sorted. The value `start_isd_as` - refers to the ISD-AS identifier of the first hop. + description: Attribute by which results are sorted. The value `start_isd_as` refers to the ISD-AS identifier of the first hop. name: sort example: expiration schema: @@ -558,10 +538,7 @@ paths: parameters: - in: path name: segment-id - description: >- - The segment ID of the beacon segment. If the input value is shorter - than a segment ID, but matches the prefix of the segment ID of - exactly one beacon, then this beacon is returned. + description: The segment ID of the beacon segment. If the input value is shorter than a segment ID, but matches the prefix of the segment ID of exactly one beacon, then this beacon is returned. required: true schema: $ref: '#/components/schemas/SegmentID' @@ -658,45 +635,27 @@ components: type: type: string format: uri-reference - description: >- - A URI reference that uniquely identifies the problem type only in - the context of the provided API. Opposed to the specification in - RFC-7807, it is neither recommended to be dereferencable and point - to a human-readable documentation nor globally unique for the - problem type. + description: A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. default: about:blank example: /problem/connection-error title: type: string - description: >- - A short summary of the problem type. Written in English and readable - for engineers, usually not suited for non technical stakeholders and - not localized. + description: A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Service Unavailable status: type: integer - description: >- - The HTTP status code generated by the origin server for this - occurrence of the problem. + description: The HTTP status code generated by the origin server for this occurrence of the problem. minimum: 100 maximum: 599 example: 503 detail: type: string - description: >- - A human readable explanation specific to this occurrence of the - problem that is helpful to locate the problem and give advice on how - to proceed. Written in English and readable for engineers, usually - not suited for non technical stakeholders and not localized. + description: A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Connection to database timed out instance: type: string format: uri-reference - description: >- - A URI reference that identifies the specific occurrence of the - problem, e.g. by adding a fragment identifier or sub-path to the - problem type. May be used to locate the root of this problem in the - source code. + description: A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. example: /problem/connection-error#token-info-read-timed-out Hop: title: Path segment hop diff --git a/spec/cppki.gen.yml b/spec/cppki.gen.yml index a92e7ece2..d2e5da792 100644 --- a/spec/cppki.gen.yml +++ b/spec/cppki.gen.yml @@ -10,10 +10,7 @@ paths: tags: - cppki summary: List the TRCs - description: >- - List the latest SCION Trust Root Configurations for each ISD that are - known to the control service. The result can be filtered by ISD. - Optionally, all TRCs can be requested instead of only the latest ones. + description: List the latest SCION Trust Root Configurations for each ISD that are known to the control service. The result can be filtered by ISD. Optionally, all TRCs can be requested instead of only the latest ones. operationId: get-trcs parameters: - in: query @@ -374,45 +371,27 @@ components: type: type: string format: uri-reference - description: >- - A URI reference that uniquely identifies the problem type only in - the context of the provided API. Opposed to the specification in - RFC-7807, it is neither recommended to be dereferencable and point - to a human-readable documentation nor globally unique for the - problem type. + description: A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. default: about:blank example: /problem/connection-error title: type: string - description: >- - A short summary of the problem type. Written in English and readable - for engineers, usually not suited for non technical stakeholders and - not localized. + description: A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Service Unavailable status: type: integer - description: >- - The HTTP status code generated by the origin server for this - occurrence of the problem. + description: The HTTP status code generated by the origin server for this occurrence of the problem. minimum: 100 maximum: 599 example: 503 detail: type: string - description: >- - A human readable explanation specific to this occurrence of the - problem that is helpful to locate the problem and give advice on how - to proceed. Written in English and readable for engineers, usually - not suited for non technical stakeholders and not localized. + description: A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Connection to database timed out instance: type: string format: uri-reference - description: >- - A URI reference that identifies the specific occurrence of the - problem, e.g. by adding a fragment identifier or sub-path to the - problem type. May be used to locate the root of this problem in the - source code. + description: A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. example: /problem/connection-error#token-info-read-timed-out responses: BadRequest: diff --git a/spec/daemon.gen.yml b/spec/daemon.gen.yml index e45fd294d..4a29ab1a9 100644 --- a/spec/daemon.gen.yml +++ b/spec/daemon.gen.yml @@ -90,10 +90,7 @@ paths: tags: - segment summary: List the SCION path segments - description: >- - List the SCION path segments that are known to the service. The results - can be filtered by the start and end AS of the segment. Inspect the - individual segments for a more detailed view. + description: List the SCION path segments that are known to the service. The results can be filtered by the start and end AS of the segment. Inspect the individual segments for a more detailed view. operationId: get-segments parameters: - in: query @@ -186,10 +183,7 @@ paths: tags: - cppki summary: List the TRCs - description: >- - List the latest SCION Trust Root Configurations for each ISD that are - known to the control service. The result can be filtered by ISD. - Optionally, all TRCs can be requested instead of only the latest ones. + description: List the latest SCION Trust Root Configurations for each ISD that are known to the control service. The result can be filtered by ISD. Optionally, all TRCs can be requested instead of only the latest ones. operationId: get-trcs parameters: - in: query @@ -450,45 +444,27 @@ components: type: type: string format: uri-reference - description: >- - A URI reference that uniquely identifies the problem type only in - the context of the provided API. Opposed to the specification in - RFC-7807, it is neither recommended to be dereferencable and point - to a human-readable documentation nor globally unique for the - problem type. + description: A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. default: about:blank example: /problem/connection-error title: type: string - description: >- - A short summary of the problem type. Written in English and readable - for engineers, usually not suited for non technical stakeholders and - not localized. + description: A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Service Unavailable status: type: integer - description: >- - The HTTP status code generated by the origin server for this - occurrence of the problem. + description: The HTTP status code generated by the origin server for this occurrence of the problem. minimum: 100 maximum: 599 example: 503 detail: type: string - description: >- - A human readable explanation specific to this occurrence of the - problem that is helpful to locate the problem and give advice on how - to proceed. Written in English and readable for engineers, usually - not suited for non technical stakeholders and not localized. + description: A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Connection to database timed out instance: type: string format: uri-reference - description: >- - A URI reference that identifies the specific occurrence of the - problem, e.g. by adding a fragment identifier or sub-path to the - problem type. May be used to locate the root of this problem in the - source code. + description: A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. example: /problem/connection-error#token-info-read-timed-out Hop: title: Path segment hop diff --git a/spec/router.gen.yml b/spec/router.gen.yml index b1b577036..9c925b403 100644 --- a/spec/router.gen.yml +++ b/spec/router.gen.yml @@ -145,10 +145,7 @@ components: type: string example: 192.168.2.2:31000 ScionMTU: - description: >- - The maximum transmission unit in bytes for SCION packets. This - represents the protocol data unit (PDU) of the SCION layer and is - usually calculated as maximum Ethernet payload - IP Header - UDP Header. + description: The maximum transmission unit in bytes for SCION packets. This represents the protocol data unit (PDU) of the SCION layer and is usually calculated as maximum Ethernet payload - IP Header - UDP Header. type: integer example: 1472 BFD: @@ -161,35 +158,19 @@ components: - required_minimum_receive properties: desired_minimum_tx_interval: - description: >- - The minimum interval between transmission of BFD control packets - that the operator desires. This value is advertised to the peer, - however the actual interval used is specified by taking the maximum - of desired-minimum-tx-interval and the value of the remote - required-minimum-receive interval value. + description: The minimum interval between transmission of BFD control packets that the operator desires. This value is advertised to the peer, however the actual interval used is specified by taking the maximum of desired-minimum-tx-interval and the value of the remote required-minimum-receive interval value. type: string example: 200ms detection_multiplier: - description: >- - The number of packets that must be missed to declare this session as - down. The detection interval for the BFD session is calculated by - multiplying the value of the negotiated transmission interval by - this value. + description: The number of packets that must be missed to declare this session as down. The detection interval for the BFD session is calculated by multiplying the value of the negotiated transmission interval by this value. type: integer example: 3 enabled: - description: >- - Indication of whether BFD is enabled and configured on this - interface. + description: Indication of whether BFD is enabled and configured on this interface. type: boolean example: true required_minimum_receive: - description: >- - The minimum interval between received BFD control packets that this - system should support. This value is advertised to the remote peer - to indicate the maximum frequency (i.e., minimum inter-packet - interval) between BFD control packets that is acceptable to the - local system. + description: The minimum interval between received BFD control packets that this system should support. This value is advertised to the remote peer to indicate the maximum frequency (i.e., minimum inter-packet interval) between BFD control packets that is acceptable to the local system. type: string example: 200ms LinkState: @@ -292,45 +273,27 @@ components: type: type: string format: uri-reference - description: >- - A URI reference that uniquely identifies the problem type only in - the context of the provided API. Opposed to the specification in - RFC-7807, it is neither recommended to be dereferencable and point - to a human-readable documentation nor globally unique for the - problem type. + description: A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. default: about:blank example: /problem/connection-error title: type: string - description: >- - A short summary of the problem type. Written in English and readable - for engineers, usually not suited for non technical stakeholders and - not localized. + description: A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Service Unavailable status: type: integer - description: >- - The HTTP status code generated by the origin server for this - occurrence of the problem. + description: The HTTP status code generated by the origin server for this occurrence of the problem. minimum: 100 maximum: 599 example: 503 detail: type: string - description: >- - A human readable explanation specific to this occurrence of the - problem that is helpful to locate the problem and give advice on how - to proceed. Written in English and readable for engineers, usually - not suited for non technical stakeholders and not localized. + description: A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Connection to database timed out instance: type: string format: uri-reference - description: >- - A URI reference that identifies the specific occurrence of the - problem, e.g. by adding a fragment identifier or sub-path to the - problem type. May be used to locate the root of this problem in the - source code. + description: A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. example: /problem/connection-error#token-info-read-timed-out responses: BadRequest: diff --git a/spec/segments.gen.yml b/spec/segments.gen.yml index 580a6a96e..fb570d4de 100644 --- a/spec/segments.gen.yml +++ b/spec/segments.gen.yml @@ -10,10 +10,7 @@ paths: tags: - segment summary: List the SCION path segments - description: >- - List the SCION path segments that are known to the service. The results - can be filtered by the start and end AS of the segment. Inspect the - individual segments for a more detailed view. + description: List the SCION path segments that are known to the service. The results can be filtered by the start and end AS of the segment. Inspect the individual segments for a more detailed view. operationId: get-segments parameters: - in: query @@ -178,43 +175,25 @@ components: type: type: string format: uri-reference - description: >- - A URI reference that uniquely identifies the problem type only in - the context of the provided API. Opposed to the specification in - RFC-7807, it is neither recommended to be dereferencable and point - to a human-readable documentation nor globally unique for the - problem type. + description: A URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type. default: about:blank example: /problem/connection-error title: type: string - description: >- - A short summary of the problem type. Written in English and readable - for engineers, usually not suited for non technical stakeholders and - not localized. + description: A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Service Unavailable status: type: integer - description: >- - The HTTP status code generated by the origin server for this - occurrence of the problem. + description: The HTTP status code generated by the origin server for this occurrence of the problem. minimum: 100 maximum: 599 example: 503 detail: type: string - description: >- - A human readable explanation specific to this occurrence of the - problem that is helpful to locate the problem and give advice on how - to proceed. Written in English and readable for engineers, usually - not suited for non technical stakeholders and not localized. + description: A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized. example: Connection to database timed out instance: type: string format: uri-reference - description: >- - A URI reference that identifies the specific occurrence of the - problem, e.g. by adding a fragment identifier or sub-path to the - problem type. May be used to locate the root of this problem in the - source code. + description: A URI reference that identifies the specific occurrence of the problem, e.g. by adding a fragment identifier or sub-path to the problem type. May be used to locate the root of this problem in the source code. example: /problem/connection-error#token-info-read-timed-out From 8b0fd65f07f3cd13bb7b695b6b778269608677dd Mon Sep 17 00:00:00 2001 From: Marc Frei Date: Thu, 16 Mar 2023 14:08:59 +0100 Subject: [PATCH 015/255] control: fix error in DRKey service engine while obtaining level 1 keys (#4326) Fix simple logic error in DRKey service engine (assignment to variable was too late, after use). --- control/drkey/service_engine.go | 6 +-- control/drkey/service_engine_test.go | 64 ++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/control/drkey/service_engine.go b/control/drkey/service_engine.go index 938494465..ffc018192 100644 --- a/control/drkey/service_engine.go +++ b/control/drkey/service_engine.go @@ -279,15 +279,15 @@ func (s *ServiceEngine) obtainLevel1Key( dstIA addr.IA, ) (drkey.Level1Key, error) { + if !proto.IsPredefined() { + proto = drkey.Generic + } level1Meta := drkey.Level1Meta{ Validity: validity, SrcIA: srcIA, DstIA: dstIA, ProtoId: proto, } - if !proto.IsPredefined() { - proto = drkey.Generic - } return s.GetLevel1Key(ctx, level1Meta) } diff --git a/control/drkey/service_engine_test.go b/control/drkey/service_engine_test.go index a72f9914e..ddf71e4b0 100644 --- a/control/drkey/service_engine_test.go +++ b/control/drkey/service_engine_test.go @@ -37,6 +37,7 @@ var ( masterKey = xtest.MustParseHexString("305554050357005ae398259bcdae7468") srcIA = xtest.MustParseIA("1-ff00:0:112") dstIA = xtest.MustParseIA("1-ff00:0:111") + srcHost = "10.1.1.12" ) func TestGetSV(t *testing.T) { @@ -94,6 +95,69 @@ func TestDeriveLevel1Key(t *testing.T) { assert.WithinDuration(t, key.Epoch.NotBefore, meta.Validity, time.Minute) } +func TestDeriveHostAS(t *testing.T) { + svdb := newSVDatabase(t) + defer svdb.Close() + + lvl1db := newLevel1Database(t) + defer lvl1db.Close() + + mctrl := gomock.NewController(t) + defer mctrl.Finish() + + fetcher := mock_drkey.NewMockFetcher(mctrl) + fetcher.EXPECT().Level1(gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, meta drkey.Level1Meta) (drkey.Level1Key, error) { + // Simulate behavior of grpc.Server.DRKeyLevel1 in package + // "github.com/scionproto/scion/control/drkey/grpc" + if !meta.ProtoId.IsPredefined() { + return drkey.Level1Key{}, serrors.New( + "the requested protocol id is not recognized", + "proto_id", meta.ProtoId) + } + return drkey.Level1Key{ + Epoch: drkey.NewEpoch(0, 1), + ProtoId: meta.ProtoId, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + }, nil + }, + ).AnyTimes() + + cache := mock_drkey.NewMockLevel1PrefetchListKeeper(mctrl) + cache.EXPECT().Update(gomock.Any()).AnyTimes() + + store := &cs_drkey.ServiceEngine{ + SecretBackend: cs_drkey.NewSecretValueBackend(svdb, masterKey, time.Minute), + LocalIA: dstIA, + DB: lvl1db, + Fetcher: fetcher, + PrefetchKeeper: cache, + } + + var tests = []drkey.Protocol{ + drkey.SCMP, + drkey.Protocol(7), + } + for _, test := range tests { + t.Run(test.String(), func(t *testing.T) { + meta := drkey.HostASMeta{ + ProtoId: test, + Validity: time.Now(), + SrcIA: srcIA, + DstIA: dstIA, + SrcHost: srcHost, + } + key, err := store.DeriveHostAS(context.Background(), meta) + assert.NoError(t, err) + assert.Equal(t, meta.ProtoId, key.ProtoId) + assert.Equal(t, meta.SrcIA, key.SrcIA) + assert.Equal(t, meta.DstIA, key.DstIA) + assert.Equal(t, meta.SrcHost, key.SrcHost) + }) + } +} + func TestGetLevel1Key(t *testing.T) { svdb := newSVDatabase(t) defer svdb.Close() From c3dc46d0aa5f4558d1cbe7cdda6a533a942c1abd Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Fri, 17 Mar 2023 11:09:23 +0100 Subject: [PATCH 016/255] topology: deprecate unused attributes (#4333) Deprecate unused attributes `authoritative`, `voting` and `issuing` from the topology.json configuration. These are no longer considered by any service or tool and the functionality has been moved into the cs.toml (containing a `[ca]` section for "issuing" ASes) or into the TRC and the configuration of the corresponding tooling. Only the `core` attribute option remains. In the long run, this should either disappear entirely from the topology configuration or be changed to a boolean flag. In the internal `private/topology`, remove the unused `CA() bool` from the interface, and simplify the representation of the state from a list of attributes to a simpler `IsCore`. The goal here is mainly to avoid confusion caused by the unused attributes. --- acceptance/topo_common/topology.json | 5 +- .../testdata/topology_reload.json | 5 +- .../testdata/topology_reload.json | 5 +- control/beaconing/testdata/topology-core.json | 5 +- private/topology/interface.go | 19 +------ private/topology/json/BUILD.bazel | 1 + private/topology/json/json.go | 42 +++++++++------- private/topology/json/json_test.go | 11 ++++- .../testdata/topology-deprecated-attrs.json | 49 +++++++++++++++++++ private/topology/json/testdata/topology.json | 5 +- private/topology/mock_topology/mock.go | 14 ------ private/topology/reload.go | 7 --- private/topology/testdata/core.json | 5 +- private/topology/topology.go | 35 ++++++------- private/topology/topology_test.go | 2 +- private/topology/validator.go | 19 ++----- private/topology/validator_test.go | 20 +++----- router/control/testdata/topology.json | 5 +- tools/topology/config.py | 2 +- tools/topology/go.py | 18 +++++-- tools/topology/topo.py | 2 +- 21 files changed, 137 insertions(+), 139 deletions(-) create mode 100644 private/topology/json/testdata/topology-deprecated-attrs.json diff --git a/acceptance/topo_common/topology.json b/acceptance/topo_common/topology.json index 147cebb3a..200ceb7b9 100644 --- a/acceptance/topo_common/topology.json +++ b/acceptance/topo_common/topology.json @@ -2,10 +2,7 @@ "isd_as": "1-ff00:0:110", "mtu": 1400, "attributes": [ - "authoritative", - "core", - "issuing", - "voting" + "core" ], "border_routers": { "br1-ff00_0_110-1": { diff --git a/acceptance/topo_cs_reload/testdata/topology_reload.json b/acceptance/topo_cs_reload/testdata/topology_reload.json index 24b2ac8f0..fdc6d6be6 100644 --- a/acceptance/topo_cs_reload/testdata/topology_reload.json +++ b/acceptance/topo_cs_reload/testdata/topology_reload.json @@ -2,10 +2,7 @@ "isd_as": "1-ff00:0:110", "mtu": 1400, "attributes": [ - "authoritative", - "core", - "issuing", - "voting" + "core" ], "border_routers": { "br1-ff00_0_110-1": { diff --git a/acceptance/topo_daemon_reload/testdata/topology_reload.json b/acceptance/topo_daemon_reload/testdata/topology_reload.json index 120b1289c..c37d92aa1 100644 --- a/acceptance/topo_daemon_reload/testdata/topology_reload.json +++ b/acceptance/topo_daemon_reload/testdata/topology_reload.json @@ -2,10 +2,7 @@ "isd_as": "1-ff00:0:110", "mtu": 1400, "attributes": [ - "authoritative", - "core", - "issuing", - "voting" + "core" ], "border_routers": { "br1-ff00_0_110-1": { diff --git a/control/beaconing/testdata/topology-core.json b/control/beaconing/testdata/topology-core.json index f01a17b53..1b37ce2bb 100644 --- a/control/beaconing/testdata/topology-core.json +++ b/control/beaconing/testdata/topology-core.json @@ -2,10 +2,7 @@ "isd_as": "1-ff00:0:110", "mtu": 1472, "attributes": [ - "authoritative", - "core", - "issuing", - "voting" + "core" ], "border_routers": { "br1-ff00_0_110-1": { diff --git a/private/topology/interface.go b/private/topology/interface.go index 485f073f6..868414d23 100644 --- a/private/topology/interface.go +++ b/private/topology/interface.go @@ -24,7 +24,6 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/serrors" - jsontopo "github.com/scionproto/scion/private/topology/json" ) // Topology is the topology type for applications and libraries that only need read access to AS @@ -39,8 +38,6 @@ type Topology interface { MTU() uint16 // Core returns whether the local AS is core. Core() bool - // CA returns whether the local AS is a CA. - CA() bool // InterfaceIDs returns all interface IDS from the local AS. InterfaceIDs() []common.IFIDType @@ -182,21 +179,7 @@ func (t *topologyS) MakeHostInfos(st ServiceType) ([]*net.UDPAddr, error) { } func (t *topologyS) Core() bool { - for _, attr := range t.Topology.Attributes { - if attr == jsontopo.AttrCore { - return true - } - } - return false -} - -func (t *topologyS) CA() bool { - for _, attr := range t.Topology.Attributes { - if attr == jsontopo.Issuing { - return true - } - } - return false + return t.Topology.IsCore } func (t *topologyS) Gateways() ([]GatewayInfo, error) { diff --git a/private/topology/json/BUILD.bazel b/private/topology/json/BUILD.bazel index 84a560ada..6c018fec4 100644 --- a/private/topology/json/BUILD.bazel +++ b/private/topology/json/BUILD.bazel @@ -6,6 +6,7 @@ go_library( importpath = "github.com/scionproto/scion/private/topology/json", visibility = ["//visibility:public"], deps = [ + "//pkg/log:go_default_library", "//pkg/private/common:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/private/util:go_default_library", diff --git a/private/topology/json/json.go b/private/topology/json/json.go index 6d2f4fbcd..08e7cf333 100644 --- a/private/topology/json/json.go +++ b/private/topology/json/json.go @@ -23,6 +23,7 @@ import ( "os" "strings" + "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/private/util" @@ -32,43 +33,50 @@ import ( type Attribute string const ( - // Authoritative indicates an authoritative AS. - Authoritative Attribute = "authoritative" // AttrCore indicates a core AS. AttrCore Attribute = "core" - // Issuing indicates an issuing AS. - Issuing Attribute = "issuing" - // Voting indicates a voting AS. A voting AS must also be a core AS. - Voting Attribute = "voting" ) -// UnmarshalText checks that the attribute is valid. It can either be -// "authoritative", "core", "issuing", or "voting". +// UnmarshalText checks that the attribute is valid. It can only be "core"; +// Deprecated values "authoritative", "issuing", or "voting" are ignored. func (t *Attribute) UnmarshalText(b []byte) error { switch Attribute(b) { - case Authoritative: - *t = Authoritative - case Issuing: - *t = Issuing - case Voting: - *t = Voting case AttrCore: *t = AttrCore + case "authoritative", "issuing", "voting": + // ignore + log.Info("topology.json; ignoring deprecated attribute value", "value", string(b)) default: return serrors.New("invalid attribute", "input", string(b)) } return nil } +type Attributes []Attribute + +func (as *Attributes) UnmarshalJSON(b []byte) error { + var attrs []Attribute + if err := json.Unmarshal(b, &attrs); err != nil { + return err + } + var filtered Attributes + for _, a := range attrs { + if a != "" { // drop ignored deprecated values + filtered = append(filtered, a) + } + } + *as = filtered + return nil +} + // Topology is the JSON type for the entire AS topology file. type Topology struct { Timestamp int64 `json:"timestamp,omitempty"` TimestampHuman string `json:"timestamp_human,omitempty"` IA string `json:"isd_as"` MTU int `json:"mtu"` - // Attributes are the primary AS attributes as described in - // https://github.com/scionproto/scion/blob/master/doc/ControlPlanePKI.md#primary-ases - Attributes []Attribute `json:"attributes"` + // Attributes specify whether this is a core AS or not. + Attributes Attributes `json:"attributes"` BorderRouters map[string]*BRInfo `json:"border_routers,omitempty"` ControlService map[string]*ServerInfo `json:"control_service,omitempty"` DiscoveryService map[string]*ServerInfo `json:"discovery_service,omitempty"` diff --git a/private/topology/json/json_test.go b/private/topology/json/json_test.go index 7d639c994..e06632749 100644 --- a/private/topology/json/json_test.go +++ b/private/topology/json/json_test.go @@ -41,8 +41,7 @@ func TestLoadRawFromFile(t *testing.T) { TimestampHuman: "May 6 00:00:00 CET 1975", IA: "6-ff00:0:362", MTU: 1472, - Attributes: []jsontopo.Attribute{jsontopo.Authoritative, jsontopo.AttrCore, - jsontopo.Issuing, jsontopo.Voting}, + Attributes: []jsontopo.Attribute{jsontopo.AttrCore}, BorderRouters: map[string]*jsontopo.BRInfo{ "borderrouter6-f00:0:362-1": { InternalAddr: "10.1.0.1:0", @@ -106,3 +105,11 @@ func TestLoadRawFromFile(t *testing.T) { ) }) } + +func TestLoadIgnoreDeprecatedAttributes(t *testing.T) { + reference, err := jsontopo.LoadFromFile("testdata/topology.json") + require.NoError(t, err) + legacyFiltered, err := jsontopo.LoadFromFile("testdata/topology-deprecated-attrs.json") + assert.NoError(t, err) + assert.Equal(t, reference, legacyFiltered) +} diff --git a/private/topology/json/testdata/topology-deprecated-attrs.json b/private/topology/json/testdata/topology-deprecated-attrs.json new file mode 100644 index 000000000..479ef6f8f --- /dev/null +++ b/private/topology/json/testdata/topology-deprecated-attrs.json @@ -0,0 +1,49 @@ +{ + "timestamp": 168562800, + "timestamp_human": "May 6 00:00:00 CET 1975", + "isd_as": "6-ff00:0:362", + "mtu": 1472, + "attributes": [ + "authoritative", + "core", + "issuing", + "voting" + ], + "border_routers": { + "borderrouter6-f00:0:362-1": { + "internal_addr": "10.1.0.1:0", + "interfaces": { + "91": { + "underlay": { + "public": "192.0.2.1:4997", + "remote": "192.0.2.2:4998", + "bind": "10.0.0.1" + }, + "isd_as": "6-ff00:0:363", + "link_to": "CORE", + "mtu": 1472, + "bfd": { + "detect_mult": 3, + "desired_min_tx_interval": "25ms", + "required_min_rx_interval": "25ms" + } + } + } + }, + "borderrouter6-f00:0:362-9": { + "internal_addr": "[2001:db8:a0b:12f0::2]:0", + "interfaces": { + "32": { + "underlay": { + "public": "[2001:db8:a0b:12f0::1]:4997", + "remote": "[2001:db8:a0b:12f0::2]:4998", + "bind": "2001:db8:a0b:12f0::8" + }, + "isd_as": "6-ff00:0:364", + "link_to": "CHILD", + "mtu": 4430 + } + } + } + } +} diff --git a/private/topology/json/testdata/topology.json b/private/topology/json/testdata/topology.json index 479ef6f8f..562d4ad08 100644 --- a/private/topology/json/testdata/topology.json +++ b/private/topology/json/testdata/topology.json @@ -4,10 +4,7 @@ "isd_as": "6-ff00:0:362", "mtu": 1472, "attributes": [ - "authoritative", - "core", - "issuing", - "voting" + "core" ], "border_routers": { "borderrouter6-f00:0:362-1": { diff --git a/private/topology/mock_topology/mock.go b/private/topology/mock_topology/mock.go index fdcac2f0b..62832c8b4 100644 --- a/private/topology/mock_topology/mock.go +++ b/private/topology/mock_topology/mock.go @@ -81,20 +81,6 @@ func (mr *MockTopologyMockRecorder) BRNames() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BRNames", reflect.TypeOf((*MockTopology)(nil).BRNames)) } -// CA mocks base method. -func (m *MockTopology) CA() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CA") - ret0, _ := ret[0].(bool) - return ret0 -} - -// CA indicates an expected call of CA. -func (mr *MockTopologyMockRecorder) CA() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CA", reflect.TypeOf((*MockTopology)(nil).CA)) -} - // Core mocks base method. func (m *MockTopology) Core() bool { m.ctrl.T.Helper() diff --git a/private/topology/reload.go b/private/topology/reload.go index 7cac38594..196174b18 100644 --- a/private/topology/reload.go +++ b/private/topology/reload.go @@ -129,13 +129,6 @@ func (l *Loader) Core() bool { return l.topo.Core() } -func (l *Loader) CA() bool { - l.mtx.Lock() - defer l.mtx.Unlock() - - return l.topo.CA() -} - func (l *Loader) UnderlayNextHop(ifID uint16) *net.UDPAddr { l.mtx.Lock() defer l.mtx.Unlock() diff --git a/private/topology/testdata/core.json b/private/topology/testdata/core.json index a8ca583b7..3f5505a8b 100644 --- a/private/topology/testdata/core.json +++ b/private/topology/testdata/core.json @@ -4,10 +4,7 @@ "isd_as": "6-ff00:0:362", "mtu": 1472, "attributes": [ - "authoritative", - "core", - "issuing", - "voting" + "core" ], "border_routers": { "borderrouter6-ff00:0:362-1": { diff --git a/private/topology/topology.go b/private/topology/topology.go index b2e3c4076..56bc02321 100644 --- a/private/topology/topology.go +++ b/private/topology/topology.go @@ -58,10 +58,10 @@ type ( // there is again a sorted slice of names of the servers that provide the service. // Additionally, there is a map from those names to TopoAddr structs. RWTopology struct { - Timestamp time.Time - IA addr.IA - Attributes []jsontopo.Attribute - MTU int + Timestamp time.Time + IA addr.IA + IsCore bool + MTU int BR map[string]BRInfo BRNames []string @@ -200,7 +200,15 @@ func (t *RWTopology) populateMeta(raw *jsontopo.Topology) error { return serrors.New("ISD-AS contains wildcard", "isd_as", t.IA) } t.MTU = raw.MTU - t.Attributes = raw.Attributes + + isCore := false + for _, attr := range raw.Attributes { + if attr == jsontopo.AttrCore { + isCore = true + break + } + } + t.IsCore = isCore return nil } @@ -235,14 +243,7 @@ func (t *RWTopology) populateBR(raw *jsontopo.Topology) error { return err } ifinfo.LinkType = LinkTypeFromString(rawIntf.LinkTo) - isCore := false - for _, attr := range t.Attributes { - if attr == jsontopo.AttrCore { - isCore = true - break - } - } - if err = ifinfo.CheckLinks(isCore, name); err != nil { + if err = ifinfo.CheckLinks(t.IsCore, name); err != nil { return err } if bfd := rawIntf.BFD; bfd != nil { @@ -373,10 +374,10 @@ func (t *RWTopology) Copy() *RWTopology { return nil } return &RWTopology{ - Timestamp: t.Timestamp, - IA: t.IA, - MTU: t.MTU, - Attributes: append(t.Attributes[:0:0], t.Attributes...), + Timestamp: t.Timestamp, + IA: t.IA, + MTU: t.MTU, + IsCore: t.IsCore, BR: copyBRMap(t.BR), BRNames: append(t.BRNames[:0:0], t.BRNames...), diff --git a/private/topology/topology_test.go b/private/topology/topology_test.go index adcc1f92a..ad0687ffe 100644 --- a/private/topology/topology_test.go +++ b/private/topology/topology_test.go @@ -35,7 +35,7 @@ func TestMeta(t *testing.T) { assert.Equal(t, time.Unix(168570123, 0), c.Timestamp, "Field 'Timestamp'") assert.Equal(t, addr.MustIAFrom(1, 0xff0000000311), c.IA, "Field 'ISD_AS'") assert.Equal(t, 1472, c.MTU, "Field 'MTU'") - assert.Empty(t, c.Attributes, "Field 'Attributes'") + assert.False(t, c.IsCore, "Field 'Attributes'") } func TestActive(t *testing.T) { diff --git a/private/topology/validator.go b/private/topology/validator.go index 9be9173e1..d46d56f11 100644 --- a/private/topology/validator.go +++ b/private/topology/validator.go @@ -19,7 +19,6 @@ import ( "sync" "github.com/scionproto/scion/pkg/private/serrors" - jsontopo "github.com/scionproto/scion/private/topology/json" ) // DefaultValidator is the default topology update validator. @@ -122,9 +121,9 @@ func (v *generalValidator) Immutable(new, old *RWTopology) error { return serrors.New("IA is immutable", "expected", old.IA, "actual", new.IA) } - if !attributesEqual(new.Attributes, old.Attributes) { - return serrors.New("Attributes are immutable", - "expected", old.Attributes, "actual", new.Attributes) + if new.IsCore != old.IsCore { + return serrors.New("IsCore is immutable", + "expected", old.IsCore, "actual", new.IsCore) } if new.MTU != old.MTU { return serrors.New("MTU is immutable", @@ -201,15 +200,3 @@ func (v *routerValidator) Immutable(new, old *RWTopology) error { } return nil } - -func attributesEqual(a, b []jsontopo.Attribute) bool { - if len(a) != len(b) { - return false - } - for i := range a { - if a[i] != b[i] { - return false - } - } - return true -} diff --git a/private/topology/validator_test.go b/private/topology/validator_test.go index ecf24dbd8..ce69469a7 100644 --- a/private/topology/validator_test.go +++ b/private/topology/validator_test.go @@ -24,7 +24,6 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/private/topology" - jsontopo "github.com/scionproto/scion/private/topology/json" ) func TestDefaultValidatorValidate(t *testing.T) { @@ -54,9 +53,8 @@ func TestDefaultValidatorValidate(t *testing.T) { assertErr: assert.Error, }, "attributes immutable": { - loadOld: defaultTopo, - loadNew: topoWithModification(t, - setAttributes([]jsontopo.Attribute{jsontopo.AttrCore})), + loadOld: defaultTopo, + loadNew: topoWithModification(t, setIsCore(true)), assertErr: assert.Error, }, "valid update": { @@ -114,9 +112,8 @@ func TestControlValidatorValidate(t *testing.T) { assertErr: assert.Error, }, "attributes immutable": { - loadOld: defaultTopo, - loadNew: topoWithModification(t, - setAttributes([]jsontopo.Attribute{jsontopo.AttrCore})), + loadOld: defaultTopo, + loadNew: topoWithModification(t, setIsCore(true)), assertErr: assert.Error, }, "valid update": { @@ -192,9 +189,8 @@ func TestRouterValidatorValidate(t *testing.T) { assertErr: assert.Error, }, "attributes immutable": { - loadOld: defaultTopo, - loadNew: topoWithModification(t, - setAttributes([]jsontopo.Attribute{jsontopo.AttrCore})), + loadOld: defaultTopo, + loadNew: topoWithModification(t, setIsCore(true)), assertErr: assert.Error, }, "valid update": { @@ -259,9 +255,9 @@ func setMTU(mtu int) func(topo *topology.RWTopology) { } } -func setAttributes(attrs []jsontopo.Attribute) func(topo *topology.RWTopology) { +func setIsCore(isCore bool) func(topo *topology.RWTopology) { return func(topo *topology.RWTopology) { - topo.Attributes = attrs + topo.IsCore = isCore } } diff --git a/router/control/testdata/topology.json b/router/control/testdata/topology.json index 6eb799601..6485c148b 100644 --- a/router/control/testdata/topology.json +++ b/router/control/testdata/topology.json @@ -2,10 +2,7 @@ "isd_as": "1-ff00:0:110", "mtu": 1472, "attributes": [ - "authoritative", - "core", - "issuing", - "voting" + "core" ], "border_routers": { "br1-ff00_0_110-1": { diff --git a/tools/topology/config.py b/tools/topology/config.py index 3df0fa6c0..948ed97f8 100644 --- a/tools/topology/config.py +++ b/tools/topology/config.py @@ -134,7 +134,7 @@ def _generate_go(self, topo_dicts): go_gen.generate_disp() def _go_args(self, topo_dicts): - return GoGenArgs(self.args, topo_dicts, self.networks) + return GoGenArgs(self.args, self.topo_config, topo_dicts, self.networks) def _generate_jaeger(self, topo_dicts): args = JaegerGenArgs(self.args, topo_dicts) diff --git a/tools/topology/go.py b/tools/topology/go.py index 2ad3702d1..85e4c6371 100644 --- a/tools/topology/go.py +++ b/tools/topology/go.py @@ -25,7 +25,7 @@ # SCION from topology.util import write_file from topology.common import ( - ArgsTopoDicts, + ArgsBase, DISP_CONFIG_NAME, docker_host, prom_addr, @@ -51,9 +51,17 @@ DEFAULT_COLIBRI_TOTAL_BW = 1000 -class GoGenArgs(ArgsTopoDicts): - def __init__(self, args, topo_dicts, networks: Mapping[IPNetwork, NetworkDescription]): - super().__init__(args, topo_dicts) +class GoGenArgs(ArgsBase): + def __init__(self, args, topo_config, topo_dicts, + networks: Mapping[IPNetwork, NetworkDescription]): + """ + :param object args: Contains the passed command line arguments as named attributes. + :param dict topo_config: The parsed topology config. + :param dict topo_dicts: The generated topo dicts from TopoGenerator. + """ + super().__init__(args) + self.config = topo_config + self.topo_dicts = topo_dicts self.networks = networks @@ -95,7 +103,7 @@ def _build_br_conf(self, topo_id, ia, base, name, v): def generate_control_service(self): for topo_id, topo in self.args.topo_dicts.items(): - ca = 'issuing' in topo.get("attributes", []) + ca = self.args.config["ASes"][str(topo_id)].get("issuing", False) for elem_id, elem in topo.get("control_service", {}).items(): # only a single Go-BS per AS is currently supported if elem_id.endswith("-1"): diff --git a/tools/topology/topo.py b/tools/topology/topo.py index 7ee56ea15..46f8c9a58 100644 --- a/tools/topology/topo.py +++ b/tools/topology/topo.py @@ -238,7 +238,7 @@ def _generate_as_topo(self, topo_id, as_conf): mtu = as_conf.get('mtu', self.args.default_mtu) assert mtu >= SCION_MIN_MTU, mtu attributes = [] - for attr in ['authoritative', 'core', 'issuing', 'voting']: + for attr in ['core']: if as_conf.get(attr, False): attributes.append(attr) self.topo_dicts[topo_id] = { From 526dc93a011ff773c045737872d14ecb40c1cac8 Mon Sep 17 00:00:00 2001 From: Marc Frei Date: Mon, 3 Apr 2023 08:41:20 +0200 Subject: [PATCH 017/255] drkey: add generic-protocol derivation to demo and integration test (#4332) Add demo/integration test for key derivation with different protocols identifiers, in particular for a "niche" protocol using the generic key derivation. Make fetching the SV optional for the server-side demo and use the non-privileged derivation mechanism otherwise. --- demo/drkey/BUILD.bazel | 1 + demo/drkey/main.go | 132 +++++++++++++++++++++++++++++++---------- demo/drkey/test.py | 99 +++++++++++++++++-------------- 3 files changed, 155 insertions(+), 77 deletions(-) diff --git a/demo/drkey/BUILD.bazel b/demo/drkey/BUILD.bazel index d677d1a2e..1479aa40e 100644 --- a/demo/drkey/BUILD.bazel +++ b/demo/drkey/BUILD.bazel @@ -22,6 +22,7 @@ go_library( "//pkg/addr:go_default_library", "//pkg/daemon:go_default_library", "//pkg/drkey:go_default_library", + "//pkg/drkey/generic:go_default_library", "//pkg/drkey/specific:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/proto/control_plane:go_default_library", diff --git a/demo/drkey/main.go b/demo/drkey/main.go index f412a9632..3337fabd7 100644 --- a/demo/drkey/main.go +++ b/demo/drkey/main.go @@ -28,6 +28,7 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/daemon" "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/drkey/generic" "github.com/scionproto/scion/pkg/drkey/specific" "github.com/scionproto/scion/pkg/private/serrors" cppb "github.com/scionproto/scion/pkg/proto/control_plane" @@ -44,13 +45,18 @@ func main() { func realMain() int { var serverMode bool var serverAddrStr, clientAddrStr string + var protocol uint16 + var fetchSV bool var scionEnv env.SCIONEnvironment scionEnv.Register(flag.CommandLine) - flag.BoolVar(&serverMode, "server", false, "Demonstrate server-side key derivation"+ - " (default: demonstrate client-side key fetching)") + flag.BoolVar(&serverMode, "server", false, "Demonstrate server-side key derivation."+ + " (default demonstrate client-side key fetching)") flag.StringVar(&serverAddrStr, "server-addr", "", "SCION address for the server-side.") flag.StringVar(&clientAddrStr, "client-addr", "", "SCION address for the client-side.") + flag.Uint16Var(&protocol, "protocol", 1 /* SCMP */, "DRKey protocol identifier.") + flag.BoolVar(&fetchSV, "fetch-sv", false, + "Fetch protocol specific secret value to derive server-side keys.") flag.Parse() if err := scionEnv.LoadExternalVars(); err != nil { fmt.Fprintln(os.Stderr, "Error reading SCION environment:", err) @@ -70,12 +76,17 @@ func realMain() int { return 2 } + if !serverMode && fetchSV { + fmt.Fprintf(os.Stderr, "Invalid flag --fetch-sv for client-side key derivation\n") + return 2 + } + ctx, cancelF := context.WithTimeout(context.Background(), 10*time.Second) defer cancelF() // meta describes the key that both client and server derive meta := drkey.HostHostMeta{ - ProtoId: drkey.SCMP, + ProtoId: drkey.Protocol(protocol), // Validity timestamp; both sides need to use a validity time stamp in the same epoch. // Usually this is coordinated by means of a timestamp in the message. Validity: time.Now(), @@ -99,28 +110,55 @@ func realMain() int { // Server: get the Secret Value (SV) for the protocol and derive all // subsequent keys in-process server := Server{daemon} - // Fetch the Secret Value (SV); in a real application, this is only done at - // startup and refreshed for each epoch. - sv, err := server.fetchSV(ctx, drkey.SecretValueMeta{ - Validity: meta.Validity, - ProtoId: meta.ProtoId, - }) - if err != nil { - fmt.Fprintln(os.Stderr, "Error fetching secret value:", err) - return 1 - } - t0 := time.Now() - serverKey, err := server.DeriveHostHostKey(sv, meta) - if err != nil { - fmt.Fprintln(os.Stderr, "Error deriving key:", err) - return 1 + var serverKey drkey.HostHostKey + var t0, t1, t2 time.Time + if fetchSV { + // Fetch the Secret Value (SV); in a real application, this is only done at + // startup and refreshed for each epoch. + t0 = time.Now() + sv, err := server.FetchSV(ctx, drkey.SecretValueMeta{ + ProtoId: meta.ProtoId, + Validity: meta.Validity, + }) + if err != nil { + fmt.Fprintln(os.Stderr, "Error fetching secret value:", err) + return 1 + } + t1 = time.Now() + serverKey, err = server.DeriveHostHostKeySpecific(sv, meta) + if err != nil { + fmt.Fprintln(os.Stderr, "Error deriving key:", err) + return 1 + } + t2 = time.Now() + } else { + // Fetch host-AS key (Level 2). This key can be used to derive keys for + // all hosts in the destination AS. Depending on the application, it can + // be cached and refreshed for each epoch. + t0 = time.Now() + hostASKey, err := server.FetchHostASKey(ctx, drkey.HostASMeta{ + ProtoId: meta.ProtoId, + Validity: meta.Validity, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + SrcHost: meta.SrcHost, + }) + if err != nil { + fmt.Fprintln(os.Stderr, "Error fetching host-AS key:", err) + return 1 + } + t1 = time.Now() + serverKey, err = server.DeriveHostHostKeyGeneric(hostASKey, meta) + if err != nil { + fmt.Fprintln(os.Stderr, "Error deriving key:", err) + return 1 + } + t2 = time.Now() } - durationServer := time.Since(t0) - fmt.Printf( - "Server,\thost key = %s\tduration = %s\n", - hex.EncodeToString(serverKey.Key[:]), - durationServer, + "Server: host key = %s, protocol = %s, fetch-sv = %v"+ + "\n\tduration without cache: %s\n\tduration with cache: %s\n", + hex.EncodeToString(serverKey.Key[:]), meta.ProtoId, fetchSV, t2.Sub(t0), t2.Sub(t1), ) } else { // Client: fetch key from daemon @@ -128,18 +166,18 @@ func realMain() int { // The CS will fetch the Lvl1 key from the CS in the SrcIA (the server's AS) // and derive the Host key based on this. client := Client{daemon} - t0 := time.Now() + var t0, t1 time.Time + t0 = time.Now() clientKey, err := client.FetchHostHostKey(ctx, meta) if err != nil { fmt.Fprintln(os.Stderr, "Error fetching key:", err) return 1 } - durationClient := time.Since(t0) + t1 = time.Now() fmt.Printf( - "Client,\thost key = %s\tduration = %s\n", - hex.EncodeToString(clientKey.Key[:]), - durationClient, + "Client: host key = %s, protocol = %s\n\tduration: %s\n", + hex.EncodeToString(clientKey.Key[:]), meta.ProtoId, t1.Sub(t0), ) } return 0 @@ -152,7 +190,7 @@ type Client struct { func (c Client) FetchHostHostKey( ctx context.Context, meta drkey.HostHostMeta) (drkey.HostHostKey, error) { - // get L2 key: (slow path) + // get level 3 key: (slow path) return c.daemon.DRKeyGetHostHostKey(ctx, meta) } @@ -160,7 +198,7 @@ type Server struct { daemon daemon.Connector } -func (s Server) DeriveHostHostKey( +func (s Server) DeriveHostHostKeySpecific( sv drkey.SecretValue, meta drkey.HostHostMeta, ) (drkey.HostHostKey, error) { @@ -189,11 +227,34 @@ func (s Server) DeriveHostHostKey( }, nil } -// fetchSV obtains the Secret Value (SV) for the selected protocol/epoch. +func (s Server) DeriveHostHostKeyGeneric( + hostAS drkey.HostASKey, + meta drkey.HostHostMeta, +) (drkey.HostHostKey, error) { + + deriver := generic.Deriver{ + Proto: hostAS.ProtoId, + } + hosthost, err := deriver.DeriveHostHost(meta.DstHost, hostAS.Key) + if err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("deriving host-host key", err) + } + return drkey.HostHostKey{ + ProtoId: hostAS.ProtoId, + Epoch: hostAS.Epoch, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + SrcHost: meta.SrcHost, + DstHost: meta.DstHost, + Key: hosthost, + }, nil +} + +// FetchSV obtains the Secret Value (SV) for the selected protocol/epoch. // From this SV, all keys for this protocol/epoch can be derived locally. // The IP address of the server must be explicitly allowed to abtain this SV // from the the control server. -func (s Server) fetchSV( +func (s Server) FetchSV( ctx context.Context, meta drkey.SecretValueMeta, ) (drkey.SecretValue, error) { @@ -256,3 +317,10 @@ func getSecretFromReply( copy(returningKey.Key[:], rep.Key) return returningKey, nil } + +func (s Server) FetchHostASKey( + ctx context.Context, meta drkey.HostASMeta) (drkey.HostASKey, error) { + + // get level 2 key: (fast path) + return s.daemon.DRKeyGetHostASKey(ctx, meta) +} diff --git a/demo/drkey/test.py b/demo/drkey/test.py index 30eab6e3e..19f08d40c 100644 --- a/demo/drkey/test.py +++ b/demo/drkey/test.py @@ -68,11 +68,12 @@ def setup_prepare(self): } }, [conf_dir / "sd.toml"]) - # Enable delegation for demo "server", i.e. allow server to - # access the base secret value from which keys can be derived locally. - server_ip = self._container_ip("scion_disp_tester_%s" % self.server_isd_as.file_fmt()) - server_cs_config = self._conf_dir(self.server_isd_as) // "cs*-1.toml" - scion.update_toml({"drkey.delegation.scmp": [server_ip]}, server_cs_config) + # Enable delegation for tester host on the fast side (server side), i.e. + # allow the tester host to directly request the secret value from which + # keys can be derived locally for any host. + tester_ip = self._container_ip("scion_disp_tester_%s" % self.server_isd_as.file_fmt()) + cs_config = self._conf_dir(self.server_isd_as) // "cs*-1.toml" + scion.update_toml({"drkey.delegation.scmp": [tester_ip]}, cs_config) def _run(self): time.sleep(10) # wait until CSes are all up and running @@ -85,46 +86,54 @@ def _run(self): for tester in testers: local["docker"]("cp", drkey_demo, tester + ":/bin/") - # Determine addresses for test - server_ip = self._server_ip(self.server_isd_as) - client_ip = self._client_ip(self.client_isd_as) - server_addr = "%s,%s" % (self.server_isd_as, server_ip) - client_addr = "%s,%s" % (self.client_isd_as, client_ip) - - # Demonstrate deriving key (fast) on server side - rs = self.dc.execute("tester_%s" % self.server_isd_as.file_fmt(), - "drkey-demo", "--server", - "--server-addr", server_addr, "--client-addr", client_addr) - print(rs) - - # Demonstrate obtaining key (slow) on client side - rc = self.dc.execute("tester_%s" % self.client_isd_as.file_fmt(), - "drkey-demo", - "--server-addr", server_addr, "--client-addr", client_addr) - print(rc) - - # Extract printed keys from output and verify that the keys match - key_regex = re.compile(r"^(?:Client|Server),\s*host key\s*=\s*([a-f0-9]+)", re.MULTILINE) - server_key_match = key_regex.search(rs) - if server_key_match is None: - raise AssertionError("Key not found in server output") - server_key = server_key_match.group(1) - client_key_match = key_regex.search(rc) - if client_key_match is None: - raise AssertionError("Key not found in client output") - client_key = client_key_match.group(1) - if server_key != client_key: - raise AssertionError("Key derived by server does not match key derived by client!", - server_key, client_key) - - def _server_ip(self, isd_as: ISD_AS) -> str: - """ Determine the IP used for the "server" in the given ISD-AS """ - return self._container_ip("scion_disp_tester_%s" % isd_as.file_fmt()) - - def _client_ip(self, isd_as: ISD_AS) -> str: - """ Determine the IP used for the "client" in the given ISD-AS """ - # The client's address must be the daemon (as this makes requests to the CS on behalf of the - # application). + # Define DRKey protocol identifiers and derivation typ for test + for test in [ + {"protocol": "1", "fetch_sv": "--fetch-sv"}, # SCMP based on protocol specific SV + {"protocol": "1", "fetch_sv": ""}, # SCMP based on generic key derivation + {"protocol": "7", "fetch_sv": ""}, # Generic "niche" protocol + ]: + # Determine server and client addresses for test. + # Because communication to the control services does not happen + # directly from the respective end hosts but via daemon processes on + # both sides, the IPs of the corresponding daemon hosts are used for + # this purpose. See also function _endhost_ip for more details. + server_ip = self._endhost_ip(self.server_isd_as) + client_ip = self._endhost_ip(self.client_isd_as) + server_addr = "%s,%s" % (self.server_isd_as, server_ip) + client_addr = "%s,%s" % (self.client_isd_as, client_ip) + + # Demonstrate deriving key (fast) on server side + rs = self.dc.execute("tester_%s" % self.server_isd_as.file_fmt(), + "drkey-demo", "--server", + "--protocol", test["protocol"], test["fetch_sv"], + "--server-addr", server_addr, "--client-addr", client_addr) + print(rs) + + # Demonstrate obtaining key (slow) on client side + rc = self.dc.execute("tester_%s" % self.client_isd_as.file_fmt(), + "drkey-demo", "--protocol", test["protocol"], + "--server-addr", server_addr, "--client-addr", client_addr) + print(rc) + + # Extract printed keys from output and verify that the keys match + key_regex = re.compile( + r"^(?:Client|Server):\s*host key\s*=\s*([a-f0-9]+)", re.MULTILINE) + server_key_match = key_regex.search(rs) + if server_key_match is None: + raise AssertionError("Key not found in server output") + server_key = server_key_match.group(1) + client_key_match = key_regex.search(rc) + if client_key_match is None: + raise AssertionError("Key not found in client output") + client_key = client_key_match.group(1) + if server_key != client_key: + raise AssertionError("Key derived by server does not match key derived by client!", + server_key, client_key) + + def _endhost_ip(self, isd_as: ISD_AS) -> str: + """ Determine the IP used for the end host (client or server) in the given ISD-AS """ + # The address must be the daemon IP (as it makes requests to the control + # service on behalf of the end host application). return self._container_ip("scion_sd%s" % isd_as.file_fmt()) def _container_ip(self, container: str) -> str: From 5ffc8c044339386449d1b57e29fe016db548085f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 13:49:06 +0200 Subject: [PATCH 018/255] rules_openapi: bump vm2 from 3.9.14 to 3.9.15 (#4335) Bumps [vm2](https://github.com/patriksimek/vm2) from 3.9.14 to 3.9.15. - [Release notes](https://github.com/patriksimek/vm2/releases) - [Changelog](https://github.com/patriksimek/vm2/blob/master/CHANGELOG.md) - [Commits](https://github.com/patriksimek/vm2/compare/3.9.14...3.9.15) vm2 is in indirect dependency of spectral-cli, which is (only!) the linter used for the openapi specs. --- updated-dependencies: - dependency-name: vm2 dependency-type: indirect Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- rules_openapi/tools/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rules_openapi/tools/yarn.lock b/rules_openapi/tools/yarn.lock index 9fb2a2d8a..c8fe601cb 100644 --- a/rules_openapi/tools/yarn.lock +++ b/rules_openapi/tools/yarn.lock @@ -3741,9 +3741,9 @@ vm-browserify@^1.0.1: integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== vm2@^3.9.8: - version "3.9.14" - resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.14.tgz#964042b474cf1e6e4f475a39144773cdb9deb734" - integrity sha512-HgvPHYHeQy8+QhzlFryvSteA4uQLBCOub02mgqdR+0bN/akRZ48TGB1v0aCv7ksyc0HXx16AZtMHKS38alc6TA== + version "3.9.15" + resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.15.tgz#c544e6a9bc31e4e40d2e5f532342cf799ea56a6e" + integrity sha512-XqNqknHGw2avJo13gbIwLNZUumvrSHc9mLqoadFZTpo3KaNEJoe1I0lqTFhRXmXD7WkLyG01aaraXdXT0pa4ag== dependencies: acorn "^8.7.0" acorn-walk "^8.2.0" From 8b41109bcfdaa8c5dc2fd49a4e3a3274aa40de16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 09:46:19 +0200 Subject: [PATCH 019/255] rules_openapi: bump vm2 from 3.9.15 to 3.9.16 (#4337) Bumps [vm2](https://github.com/patriksimek/vm2) from 3.9.15 to 3.9.16. - [Release notes](https://github.com/patriksimek/vm2/releases) - [Changelog](https://github.com/patriksimek/vm2/blob/master/CHANGELOG.md) - [Commits](https://github.com/patriksimek/vm2/compare/3.9.15...3.9.16) vm2 is an indirect dependency of spectral-cli, which is (only!) the linter used for the openapi specs. --- updated-dependencies: - dependency-name: vm2 dependency-type: indirect Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- rules_openapi/tools/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rules_openapi/tools/yarn.lock b/rules_openapi/tools/yarn.lock index c8fe601cb..1f8673936 100644 --- a/rules_openapi/tools/yarn.lock +++ b/rules_openapi/tools/yarn.lock @@ -3741,9 +3741,9 @@ vm-browserify@^1.0.1: integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== vm2@^3.9.8: - version "3.9.15" - resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.15.tgz#c544e6a9bc31e4e40d2e5f532342cf799ea56a6e" - integrity sha512-XqNqknHGw2avJo13gbIwLNZUumvrSHc9mLqoadFZTpo3KaNEJoe1I0lqTFhRXmXD7WkLyG01aaraXdXT0pa4ag== + version "3.9.16" + resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.16.tgz#0fbc2a265f7bf8b837cea6f4a908f88a3f93b8e6" + integrity sha512-3T9LscojNTxdOyG+e8gFeyBXkMlOBYDoF6dqZbj+MPVHi9x10UfiTAJIobuchRCp3QvC+inybTbMJIUrLsig0w== dependencies: acorn "^8.7.0" acorn-walk "^8.2.0" From 045c07ea751541984aee10c4bdfdb8e305dfe1f2 Mon Sep 17 00:00:00 2001 From: Antonio Battipaglia <83505887+MrR0b0t14@users.noreply.github.com> Date: Mon, 24 Apr 2023 09:21:21 +0200 Subject: [PATCH 020/255] scion.sh: fix IPv6 address bug in sciond-addr subcommand (#4341) The scion.sh sciond-addr command was returning an invalid address for IPv6 setups, resulting in "too many colons address" error when used as the `--sciond` parameter of tool invocations. Fixed by wrapping the IP in brackets before appending the port. --- scion.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scion.sh b/scion.sh index e4766dfb3..371f41027 100755 --- a/scion.sh +++ b/scion.sh @@ -55,7 +55,7 @@ cmd_sciond-addr() { jq -r 'to_entries | map(select(.key | match("'"$1"'";"i"))) | if length != 1 then error("No unique match for '"$1"'") else .[0] end | - "\(.value):30255"' gen/sciond_addresses.json + "[\(.value)]:30255"' gen/sciond_addresses.json } run_jaeger() { From 91d8cfbec689a82303ff5768a5edb0790c5307d5 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Fri, 5 May 2023 11:57:02 +0200 Subject: [PATCH 021/255] rules_openapi: add rule to build HTML doc (#4338) Add openapi_build_doc rule to build the API documentation as zero-dependency HTML file. This replaces separate genrules in the build files for the individual tools. These had all been using the `redoc-cli` command which is deprecated (in favor of redocly/cli) and had been creating broken HTML files since #4323. Fix the link in the dummy index.html page from the private/mgmtapi package, used when not bundling the generated documentation page, to point to openapi.json (not spec.json). Drop the yarn dependency on `redoc-cli` and update all dependencies. --- control/mgmtapi/BUILD.bazel | 19 +- control/mgmtapi/spec.go | 2 +- daemon/mgmtapi/BUILD.bazel | 19 +- daemon/mgmtapi/spec.go | 2 +- dispatcher/mgmtapi/BUILD.bazel | 19 +- dispatcher/mgmtapi/spec.go | 2 +- gateway/mgmtapi/BUILD.bazel | 19 +- gateway/mgmtapi/spec.go | 2 +- private/mgmtapi/index.html | 2 +- router/mgmtapi/BUILD.bazel | 19 +- router/mgmtapi/spec.go | 2 +- rules_openapi/defs.bzl | 13 + rules_openapi/internal/BUILD.bazel | 1 + rules_openapi/internal/docs.bzl | 39 + rules_openapi/tools/package.json | 3 +- rules_openapi/tools/yarn.lock | 1377 ++++------------------------ 16 files changed, 248 insertions(+), 1292 deletions(-) create mode 100644 rules_openapi/internal/docs.bzl diff --git a/control/mgmtapi/BUILD.bazel b/control/mgmtapi/BUILD.bazel index 22e82f8f9..69012989b 100644 --- a/control/mgmtapi/BUILD.bazel +++ b/control/mgmtapi/BUILD.bazel @@ -1,17 +1,10 @@ load("//tools/lint:go.bzl", "go_library", "go_test") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_generate_go") +load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs", "openapi_generate_go") -genrule( - name = "bundle", - srcs = ["//spec:control"], - outs = ["index.html"], - cmd = ( - "$(execpath @rules_openapi_npm//redoc-cli/bin:redoc-cli) " + - "bundle $(location //spec:control) " + - "-o $@" - ), - tools = ["@rules_openapi_npm//redoc-cli/bin:redoc-cli"], - visibility = ["//visibility:public"], +openapi_build_docs( + name = "doc", + src = "//spec:control", + out = "index.html", ) openapi_generate_go( @@ -30,7 +23,7 @@ go_library( ":api_generated", # keep ], embedsrcs = select({ - "//:mgmtapi_bundle_doc_build": [":bundle"], + "//:mgmtapi_bundle_doc_build": [":doc"], "//conditions:default": [":dummy.html"], }), # keep importpath = "github.com/scionproto/scion/control/mgmtapi", diff --git a/control/mgmtapi/spec.go b/control/mgmtapi/spec.go index 77f2632b9..887633ba4 100644 --- a/control/mgmtapi/spec.go +++ b/control/mgmtapi/spec.go @@ -47,5 +47,5 @@ func ServeSpecInteractive(w http.ResponseWriter, r *http.Request) { // ServeSpecJSON serves the json encoded OpenAPI3 spec. func ServeSpecJSON(w http.ResponseWriter, r *http.Request) { - http.ServeContent(w, r, "spec.json", modtime, bytes.NewReader(spec)) + http.ServeContent(w, r, "openapi.json", modtime, bytes.NewReader(spec)) } diff --git a/daemon/mgmtapi/BUILD.bazel b/daemon/mgmtapi/BUILD.bazel index 38c491dcb..33f3f3ca0 100644 --- a/daemon/mgmtapi/BUILD.bazel +++ b/daemon/mgmtapi/BUILD.bazel @@ -1,17 +1,10 @@ load("//tools/lint:go.bzl", "go_library") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_generate_go") +load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs", "openapi_generate_go") -genrule( - name = "bundle", - srcs = ["//spec:daemon"], - outs = ["index.html"], - cmd = ( - "$(execpath @rules_openapi_npm//redoc-cli/bin:redoc-cli) " + - "bundle $(location //spec:daemon) " + - "-o $@" - ), - tools = ["@rules_openapi_npm//redoc-cli/bin:redoc-cli"], - visibility = ["//visibility:public"], +openapi_build_docs( + name = "doc", + src = "//spec:daemon", + out = "index.html", ) openapi_generate_go( @@ -30,7 +23,7 @@ go_library( ":api_generated", # keep ], embedsrcs = select({ - "//:mgmtapi_bundle_doc_build": [":bundle"], + "//:mgmtapi_bundle_doc_build": [":doc"], "//conditions:default": [":dummy.html"], }), # keep importpath = "github.com/scionproto/scion/daemon/mgmtapi", diff --git a/daemon/mgmtapi/spec.go b/daemon/mgmtapi/spec.go index 77f2632b9..887633ba4 100644 --- a/daemon/mgmtapi/spec.go +++ b/daemon/mgmtapi/spec.go @@ -47,5 +47,5 @@ func ServeSpecInteractive(w http.ResponseWriter, r *http.Request) { // ServeSpecJSON serves the json encoded OpenAPI3 spec. func ServeSpecJSON(w http.ResponseWriter, r *http.Request) { - http.ServeContent(w, r, "spec.json", modtime, bytes.NewReader(spec)) + http.ServeContent(w, r, "openapi.json", modtime, bytes.NewReader(spec)) } diff --git a/dispatcher/mgmtapi/BUILD.bazel b/dispatcher/mgmtapi/BUILD.bazel index 3362726f6..d63ed1b5d 100644 --- a/dispatcher/mgmtapi/BUILD.bazel +++ b/dispatcher/mgmtapi/BUILD.bazel @@ -1,17 +1,10 @@ load("//tools/lint:go.bzl", "go_library") -load("//rules_openapi:defs.bzl", "openapi_generate_go") +load("//rules_openapi:defs.bzl", "openapi_build_docs", "openapi_generate_go") -genrule( - name = "bundle", - srcs = ["//spec:dispatcher"], - outs = ["index.html"], - cmd = ( - "$(execpath @rules_openapi_npm//redoc-cli/bin:redoc-cli) " + - "bundle $(location //spec:dispatcher) " + - "-o $@" - ), - tools = ["@rules_openapi_npm//redoc-cli/bin:redoc-cli"], - visibility = ["//visibility:public"], +openapi_build_docs( + name = "doc", + src = "//spec:dispatcher", + out = "index.html", ) openapi_generate_go( @@ -30,7 +23,7 @@ go_library( ":api_generated", # keep ], embedsrcs = select({ - "//:mgmtapi_bundle_doc_build": [":bundle"], + "//:mgmtapi_bundle_doc_build": [":doc"], "//conditions:default": [":dummy.html"], }), # keep importpath = "github.com/scionproto/scion/dispatcher/mgmtapi", diff --git a/dispatcher/mgmtapi/spec.go b/dispatcher/mgmtapi/spec.go index 77f2632b9..887633ba4 100644 --- a/dispatcher/mgmtapi/spec.go +++ b/dispatcher/mgmtapi/spec.go @@ -47,5 +47,5 @@ func ServeSpecInteractive(w http.ResponseWriter, r *http.Request) { // ServeSpecJSON serves the json encoded OpenAPI3 spec. func ServeSpecJSON(w http.ResponseWriter, r *http.Request) { - http.ServeContent(w, r, "spec.json", modtime, bytes.NewReader(spec)) + http.ServeContent(w, r, "openapi.json", modtime, bytes.NewReader(spec)) } diff --git a/gateway/mgmtapi/BUILD.bazel b/gateway/mgmtapi/BUILD.bazel index 83ea7d769..22076e129 100644 --- a/gateway/mgmtapi/BUILD.bazel +++ b/gateway/mgmtapi/BUILD.bazel @@ -1,17 +1,10 @@ load("//tools/lint:go.bzl", "go_library") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_generate_go") +load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs", "openapi_generate_go") -genrule( - name = "bundle", - srcs = ["//spec:gateway"], - outs = ["index.html"], - cmd = ( - "$(execpath @rules_openapi_npm//redoc-cli/bin:redoc-cli) " + - "bundle $(location //spec:gateway) " + - "-o $@" - ), - tools = ["@rules_openapi_npm//redoc-cli/bin:redoc-cli"], - visibility = ["//visibility:public"], +openapi_build_docs( + name = "doc", + src = "//spec:gateway", + out = "index.html", ) openapi_generate_go( @@ -30,7 +23,7 @@ go_library( ":api_generated", # keep ], embedsrcs = select({ - "//:mgmtapi_bundle_doc_build": [":bundle"], + "//:mgmtapi_bundle_doc_build": [":doc"], "//conditions:default": [":dummy.html"], }), # keep importpath = "github.com/scionproto/scion/gateway/mgmtapi", diff --git a/gateway/mgmtapi/spec.go b/gateway/mgmtapi/spec.go index 77f2632b9..887633ba4 100644 --- a/gateway/mgmtapi/spec.go +++ b/gateway/mgmtapi/spec.go @@ -47,5 +47,5 @@ func ServeSpecInteractive(w http.ResponseWriter, r *http.Request) { // ServeSpecJSON serves the json encoded OpenAPI3 spec. func ServeSpecJSON(w http.ResponseWriter, r *http.Request) { - http.ServeContent(w, r, "spec.json", modtime, bytes.NewReader(spec)) + http.ServeContent(w, r, "openapi.json", modtime, bytes.NewReader(spec)) } diff --git a/private/mgmtapi/index.html b/private/mgmtapi/index.html index 7000507fd..f5ea08849 100644 --- a/private/mgmtapi/index.html +++ b/private/mgmtapi/index.html @@ -6,7 +6,7 @@

Service Management UI not bundled

The service management UI is not bundled in this binary. - The OpenAPI spec is available at /spec.json + The OpenAPI spec is available at /openapi.json diff --git a/router/mgmtapi/BUILD.bazel b/router/mgmtapi/BUILD.bazel index 00797045f..f1d74c2a5 100644 --- a/router/mgmtapi/BUILD.bazel +++ b/router/mgmtapi/BUILD.bazel @@ -1,17 +1,10 @@ load("//tools/lint:go.bzl", "go_library", "go_test") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_generate_go") +load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs", "openapi_generate_go") -genrule( - name = "bundle", - srcs = ["//spec:router"], - outs = ["index.html"], - cmd = ( - "$(execpath @rules_openapi_npm//redoc-cli/bin:redoc-cli) " + - "bundle $(location //spec:router) " + - "-o $@" - ), - tools = ["@rules_openapi_npm//redoc-cli/bin:redoc-cli"], - visibility = ["//visibility:public"], +openapi_build_docs( + name = "doc", + src = "//spec:router", + out = "index.html", ) openapi_generate_go( @@ -30,7 +23,7 @@ go_library( ":api_generated", # keep ], embedsrcs = select({ - "//:mgmtapi_bundle_doc_build": [":bundle"], + "//:mgmtapi_bundle_doc_build": [":doc"], "//conditions:default": [":dummy.html"], }), # keep importpath = "github.com/scionproto/scion/router/mgmtapi", diff --git a/router/mgmtapi/spec.go b/router/mgmtapi/spec.go index 77f2632b9..887633ba4 100644 --- a/router/mgmtapi/spec.go +++ b/router/mgmtapi/spec.go @@ -47,5 +47,5 @@ func ServeSpecInteractive(w http.ResponseWriter, r *http.Request) { // ServeSpecJSON serves the json encoded OpenAPI3 spec. func ServeSpecJSON(w http.ResponseWriter, r *http.Request) { - http.ServeContent(w, r, "spec.json", modtime, bytes.NewReader(spec)) + http.ServeContent(w, r, "openapi.json", modtime, bytes.NewReader(spec)) } diff --git a/rules_openapi/defs.bzl b/rules_openapi/defs.bzl index 73b344381..fc537789c 100644 --- a/rules_openapi/defs.bzl +++ b/rules_openapi/defs.bzl @@ -1,5 +1,6 @@ load("//rules_openapi/internal:generate.bzl", _openapi_generate_go = "openapi_generate_go") load("//rules_openapi/internal:bundle.bzl", _openapi_bundle = "openapi_bundle") +load("//rules_openapi/internal:docs.bzl", _openapi_build_docs = "openapi_build_docs") load("//rules_openapi/internal:header.bzl", _header = "header") load("@cgrindel_bazel_starlib//updatesrc:defs.bzl", "updatesrc_update") @@ -52,3 +53,15 @@ def openapi_generate_go( srcs = srcs, outs = [":" + name], ) + +def openapi_build_docs( + name, + src, + out, + **kwargs): + _openapi_build_docs( + name = name, + src = src, + out = out, + **kwargs + ) diff --git a/rules_openapi/internal/BUILD.bazel b/rules_openapi/internal/BUILD.bazel index fa0b76361..feb4d1403 100644 --- a/rules_openapi/internal/BUILD.bazel +++ b/rules_openapi/internal/BUILD.bazel @@ -6,6 +6,7 @@ bzl_library( name = "rules_openapi_internal", srcs = [ "bundle.bzl", + "docs.bzl", "generate.bzl", "header.bzl", ], diff --git a/rules_openapi/internal/docs.bzl b/rules_openapi/internal/docs.bzl new file mode 100644 index 000000000..5f613b2ba --- /dev/null +++ b/rules_openapi/internal/docs.bzl @@ -0,0 +1,39 @@ +load("@bazel_skylib//lib:shell.bzl", "shell") + +def _openapi_build_docs_impl(ctx): + cmd = "{bin} build-docs --output {out} {src}".format( + bin = ctx.executable._openapi_cli.path, + out = shell.quote(ctx.outputs.out.path), + src = shell.quote(ctx.file.src.path), + ) + + ctx.actions.run_shell( + outputs = [ctx.outputs.out], + inputs = [ctx.file.src], + tools = [ctx.executable._openapi_cli], + command = cmd, + mnemonic = "OpenAPIBuildDocs", + use_default_shell_env = True, + ) + return [DefaultInfo( + files = depset([ctx.outputs.out]), + )] + +openapi_build_docs = rule( + implementation = _openapi_build_docs_impl, + doc = "This rule can be used to create API documentation as a single, zero-dependency HTML file.", + attrs = { + "src": attr.label( + doc = "The API definition file", + allow_single_file = [".yml"], + ), + "out": attr.output( + doc = "The output HTML file generated by this rule", + ), + "_openapi_cli": attr.label( + default = "@rules_openapi_npm//@redocly/cli/bin:openapi", + executable = True, + cfg = "target", + ), + }, +) diff --git a/rules_openapi/tools/package.json b/rules_openapi/tools/package.json index dc8fd2a9d..ae5fcb2a0 100644 --- a/rules_openapi/tools/package.json +++ b/rules_openapi/tools/package.json @@ -3,7 +3,6 @@ "@redocly/cli": "^1.0.0-beta.123", "@stoplight/spectral-cli": "^6.6.0", "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", - "redoc-cli": "^0.13.2" + "lodash.set": "^4.3.2" } } diff --git a/rules_openapi/tools/yarn.lock b/rules_openapi/tools/yarn.lock index 1f8673936..b16f2846f 100644 --- a/rules_openapi/tools/yarn.lock +++ b/rules_openapi/tools/yarn.lock @@ -3,25 +3,25 @@ "@asyncapi/specs@^4.1.0": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@asyncapi/specs/-/specs-4.1.1.tgz#3cb9fa9e1e7cf2c205d22ff4fba7ddbc41bcfb62" - integrity sha512-CtJdKTQnzX3UwHVBgwrzLIwmnlxl1VKsLNG9ORgdUoD7BFB1fEh9hjdCD3Qh3eHhvlfizLtlFlGet1yQBSi1mg== + version "4.2.0" + resolved "https://registry.yarnpkg.com/@asyncapi/specs/-/specs-4.2.0.tgz#33003051aa50785e3480c18ac7d9afbc8e68434d" + integrity sha512-V9bFzUGNXrpsyennEXNZaPvdoFYYoeUYYAGiQVYsGsUsF/IL/G40NpE9u6nPeXGj8sZgjKlUG6iP39T0DYtSlQ== dependencies: "@types/json-schema" "^7.0.11" -"@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== +"@babel/code-frame@^7.18.6", "@babel/code-frame@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" + integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== dependencies: "@babel/highlight" "^7.18.6" -"@babel/generator@^7.21.0": - version "7.21.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" - integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== +"@babel/generator@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.4.tgz#64a94b7448989f421f919d5239ef553b37bb26bc" + integrity sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA== dependencies: - "@babel/types" "^7.21.0" + "@babel/types" "^7.21.4" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" @@ -54,11 +54,11 @@ "@babel/types" "^7.18.6" "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.16.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz#ac88b2f76093637489e718a90cec6cf8a9b029af" + integrity sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.21.4" "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" @@ -86,10 +86,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.20.7", "@babel/parser@^7.21.0": - version "7.21.1" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.1.tgz#a8f81ee2fe872af23faea4b17a08fcc869de7bcc" - integrity sha512-JzhBFpkuhBNYUY7qs+wTzNmyCWUHEaAFpQQD2YfU1rPL38/L43Wvid0fFkiOCnHvsGncRZgEPyGnltABLcVDTg== +"@babel/parser@^7.20.7", "@babel/parser@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.4.tgz#94003fdfc520bbe2875d4ae557b43ddb6d880f17" + integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw== "@babel/runtime@^7.17.8": version "7.21.0" @@ -108,25 +108,25 @@ "@babel/types" "^7.20.7" "@babel/traverse@^7.4.5": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.0.tgz#0e1807abd5db98e6a19c204b80ed1e3f5bca0edc" - integrity sha512-Xdt2P1H4LKTO8ApPfnO1KmzYMFpp7D/EinoXzLYN/cHcBNrVCAkAtGUcXnHXrl/VGktureU6fkQrHSBE2URfoA== + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.4.tgz#a836aca7b116634e97a6ed99976236b3282c9d36" + integrity sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q== dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.0" + "@babel/code-frame" "^7.21.4" + "@babel/generator" "^7.21.4" "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-function-name" "^7.21.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.21.0" - "@babel/types" "^7.21.0" + "@babel/parser" "^7.21.4" + "@babel/types" "^7.21.4" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.18.6", "@babel/types@^7.20.7", "@babel/types@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.0.tgz#1da00d89c2f18b226c9207d96edbeb79316a1819" - integrity sha512-uR7NWq2VNFnDi7EYqiRz2Jv/VQIu38tu64Zy8TX2nQFQ6etJ9V/Rr2msW8BS132mum2rL645qpDrLtAJtVpuow== +"@babel/types@^7.18.6", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.4.tgz#2d5d6bb7908699b3b416409ffd3b5daa25b030d4" + integrity sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA== dependencies: "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" @@ -139,23 +139,11 @@ dependencies: "@emotion/memoize" "0.7.4" -"@emotion/is-prop-valid@^1.1.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz#7f2d35c97891669f7e276eb71c83376a5dc44c83" - integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg== - dependencies: - "@emotion/memoize" "^0.8.0" - "@emotion/memoize@0.7.4": version "0.7.4" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== -"@emotion/memoize@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" - integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== - "@emotion/stylis@^0.8.4": version "0.8.5" resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" @@ -167,14 +155,14 @@ integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== "@exodus/schemasafe@^1.0.0-rc.2": - version "1.0.0-rc.9" - resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.0.0-rc.9.tgz#56b9c6df627190f2dcda15f81f25d68826d9be4d" - integrity sha512-dGGHpb61hLwifAu7sotuHFDBw6GTdpG8aKC0fsK17EuTzMRvUrH7lEAr6LTJ+sx3AZYed9yZ77rltVDHyg2hRg== + version "1.0.0" + resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.0.0.tgz#f44e252665b1a6bdef0d686e22af3599a6f0a095" + integrity sha512-2cyupPIZI69HQxEAPllLXBjQp4njDKkOjYRCYxvMZe3/LY9pp9fBM3Tb1wiFAdP6Emo4v3OEbCLGj6u73Q5KLw== "@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== dependencies: "@jridgewell/set-array" "^1.0.1" "@jridgewell/sourcemap-codec" "^1.4.10" @@ -190,15 +178,20 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/sourcemap-codec@1.4.14": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== dependencies: "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" @@ -245,11 +238,11 @@ uri-js "^4.2.2" "@redocly/cli@^1.0.0-beta.123": - version "1.0.0-beta.123" - resolved "https://registry.yarnpkg.com/@redocly/cli/-/cli-1.0.0-beta.123.tgz#b69f221c6bf73f38b09e96f8df27d0fbdfc47e6d" - integrity sha512-aTlqewdXj0LXjh38xJ5lfa380Nyu/cq9+CmfUKXk95/5BDkbJvOjTInxndsjB/KgKbOJlx0vnEoktms0aDhtNw== + version "1.0.0-beta.125" + resolved "https://registry.yarnpkg.com/@redocly/cli/-/cli-1.0.0-beta.125.tgz#3b107579193572289b264fb12edc2127e3175dbe" + integrity sha512-3n5wtCux2vtWdxPvLs5nvbiYiEz+gkAPs/1kC/df7tzBOZ3zld6onrwuBjhMKtzJbJ1B3i1yzrfJz0mMmoNrtQ== dependencies: - "@redocly/openapi-core" "1.0.0-beta.123" + "@redocly/openapi-core" "1.0.0-beta.125" assert-node-version "^1.0.3" chokidar "^3.5.1" colorette "^1.2.0" @@ -265,10 +258,10 @@ styled-components "5.3.3" yargs "17.0.1" -"@redocly/openapi-core@1.0.0-beta.123", "@redocly/openapi-core@^1.0.0-beta.104": - version "1.0.0-beta.123" - resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.0.0-beta.123.tgz#0c29ae9fabe5f143f571caf608a7d025f41125db" - integrity sha512-W6MbUWpb/VaV+Kf0c3jmMIJw3WwwF7iK5nAfcOS+ZwrlbxtIl37+1hEydFlJ209vCR9HL12PaMwdh2Vpihj6Jw== +"@redocly/openapi-core@1.0.0-beta.125", "@redocly/openapi-core@^1.0.0-beta.104": + version "1.0.0-beta.125" + resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.0.0-beta.125.tgz#a87b7cbbbd1cef2206bcc2c6c7b498f07378466b" + integrity sha512-3kpvIP6nzqrXl59BXovm1aGcbqSJv37t9kjFxuEvsGZzVSUC8rGZl4tNEZ3Qfm+mbPs+XWDi/U43kf/u3bUCpw== dependencies: "@redocly/ajv" "^8.11.0" "@types/node" "^14.11.8" @@ -303,11 +296,6 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - "@stoplight/better-ajv-errors@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.3.tgz#d74a5c4da5d786c17188d7f4edec505f089885fa" @@ -391,9 +379,9 @@ yargs "17.3.1" "@stoplight/spectral-core@>=1", "@stoplight/spectral-core@^1.15.1", "@stoplight/spectral-core@^1.7.0", "@stoplight/spectral-core@^1.8.0", "@stoplight/spectral-core@^1.8.1": - version "1.16.1" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-core/-/spectral-core-1.16.1.tgz#a4af80c021c0be0c52b92cc7acbdacb97919ea20" - integrity sha512-zPTM/OpjUySMRLPx6ZYy9Gtw+Rkuwg1/gQTKWta+AaJjVTHrNznYQ05gFLYjWwD/LGJMdjwE2IMi7T+Ntef+kw== + version "1.17.0" + resolved "https://registry.yarnpkg.com/@stoplight/spectral-core/-/spectral-core-1.17.0.tgz#f897871f394e62ab9fdf15119730db5d82fc5e47" + integrity sha512-7D9og+iX2bCJMGPY7cvt2YdevFGDeSI7S2jPo7HWeGGitkef1FDSQ9AEapdwmCYvOJ7ztUlQdCCLTOb6Aani8w== dependencies: "@stoplight/better-ajv-errors" "1.0.3" "@stoplight/json" "~3.20.1" @@ -560,9 +548,9 @@ utility-types "^3.10.0" "@stoplight/types@^12.3.0 || ^13.0.0", "@stoplight/types@^13.0.0", "@stoplight/types@^13.6.0": - version "13.9.1" - resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-13.9.1.tgz#adaa19a3d7f8182cd7de65c592bea170f1a8c22e" - integrity sha512-IiInrb/xux6Xf+IQW6I8crbsoxLtNa1mDGQyUDbd6Tyfb9fXAGjIaA1Yb5JXNR3ChLypmd3ROUHEUNAanegGVw== + version "13.11.0" + resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-13.11.0.tgz#3a1e206770e7d5dd65c0cc9206e68be6913f2bce" + integrity sha512-jGojdysNoYytTDCmGEjxugIRllmZhYxMaOt+NtPRo/ZxjXY9mbQ6kzoNWyFiEDzjTVzYyr32ygJ/ex7/LAhvXw== dependencies: "@types/json-schema" "^7.0.4" utility-types "^3.10.0" @@ -590,13 +578,6 @@ "@stoplight/yaml-ast-parser" "0.0.48" tslib "^2.2.0" -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -638,14 +619,14 @@ integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== "@types/node@*": - version "18.14.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.0.tgz#94c47b9217bbac49d4a67a967fdcdeed89ebb7d0" - integrity sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A== + version "18.15.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" + integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== "@types/node@^14.11.8": - version "14.18.36" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.36.tgz#c414052cb9d43fab67d679d5f3c641be911f5835" - integrity sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ== + version "14.18.42" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.42.tgz#fa39b2dc8e0eba61bdf51c66502f84e23b66e114" + integrity sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg== "@types/urijs@^1.19.19": version "1.19.19" @@ -703,13 +684,6 @@ ajv@^8.0.0, ajv@^8.6.0, ajv@^8.6.3, ajv@^8.8.2: require-from-string "^2.0.2" uri-js "^4.2.2" -ansi-align@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" - integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== - dependencies: - string-width "^4.1.0" - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -742,6 +716,14 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + as-table@^1.0.36: version "1.0.55" resolved "https://registry.yarnpkg.com/as-table/-/as-table-1.0.55.tgz#dc984da3937745de902cea1d45843c01bdbbec4f" @@ -749,16 +731,6 @@ as-table@^1.0.36: dependencies: printable-characters "^1.0.42" -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - assert-node-version@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/assert-node-version/-/assert-node-version-1.0.3.tgz#caea5d1b6a58dbce59661208df1e1b9e4c580f91" @@ -767,14 +739,6 @@ assert-node-version@^1.0.3: expected-node-version "^1.0.0" semver "^5.0.3" -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - ast-types@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" @@ -807,14 +771,14 @@ available-typed-arrays@^1.0.5: integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== "babel-plugin-styled-components@>= 1.12.0": - version "2.0.7" - resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz#c81ef34b713f9da2b7d3f5550df0d1e19e798086" - integrity sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA== + version "2.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.1.tgz#cd977cc0ff8410d5cbfdd142e42576e9c8794b87" + integrity sha512-c8lJlszObVQPguHkI+akXv8+Jgb9Ccujx0EetL7oIvwU100LxO6XAGe45qry37wUL40a5U9f23SYrivro2XKhA== dependencies: "@babel/helper-annotate-as-pure" "^7.16.0" "@babel/helper-module-imports" "^7.16.0" babel-plugin-syntax-jsx "^6.18.0" - lodash "^4.17.11" + lodash "^4.17.21" picomatch "^2.3.0" babel-plugin-syntax-jsx@^6.18.0: @@ -827,40 +791,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.0.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.0.0, bn.js@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - -boxen@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" - integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^6.2.0" - chalk "^4.1.0" - cli-boxes "^2.2.1" - string-width "^4.2.2" - type-fest "^0.20.2" - widest-line "^3.1.0" - wrap-ansi "^7.0.0" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -883,91 +818,6 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.0.1, brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== - -buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== - builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" @@ -978,19 +828,6 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -1004,17 +841,12 @@ call-me-maybe@^1.0.1: resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - camelize@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== -chalk@4.1.2, chalk@^4.1.0: +chalk@4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1046,29 +878,11 @@ chokidar@^3.5.1: optionalDependencies: fsevents "~2.3.2" -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - classnames@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== -cli-boxes@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" - integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== - cliui@7.0.4, cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -1087,13 +901,6 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" -clone-response@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" - integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== - dependencies: - mimic-response "^1.0.0" - clsx@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" @@ -1138,86 +945,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -configstore@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" - integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== - dependencies: - dot-prop "^5.2.0" - graceful-fs "^4.1.2" - make-dir "^3.0.0" - unique-string "^2.0.0" - write-file-atomic "^3.0.0" - xdg-basedir "^4.0.0" - -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== - core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - css-color-keywords@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" @@ -1261,28 +993,11 @@ decko@^1.2.0: resolved "https://registry.yarnpkg.com/decko/-/decko-1.2.0.tgz#fd43c735e967b8013306884a56fbe665996b6817" integrity sha512-m8FnyHXV1QX+S1cl+KPFDIl6NMkxtKsy6+U/aYyjrOqWMuwAwYWu7ePqrsUHtDR5Y8Yk2pi/KIDSgF+vT4cPOQ== -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== - dependencies: - mimic-response "^1.0.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - define-properties@^1.1.3, define-properties@^1.1.4: version "1.2.0" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" @@ -1292,14 +1007,14 @@ define-properties@^1.1.3, define-properties@^1.1.4: object-keys "^1.1.1" degenerator@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-3.0.2.tgz#6a61fcc42a702d6e50ff6023fe17bff435f68235" - integrity sha512-c0mef3SNQo56t6urUU6tdQAs+ThoD0o9B9MJ8HEt7NQcGEILCRFqQb7ZbP9JAv+QF1Ky5plydhMR/IrqWDm+TQ== + version "3.0.3" + resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-3.0.3.tgz#a081ac30052ca84e1d1c6e86c972ae8dabbc4079" + integrity sha512-FTq/qYMeBJACu1gHcXJvzsRBTK6aw5zWCYbEnIOyamOt5UJufWJRQ5XfDb6OuayfJWvmWAHgcZyt43vm/hbj7g== dependencies: ast-types "^0.13.2" escodegen "^1.8.1" esprima "^4.0.0" - vm2 "^3.9.8" + vm2 "^3.9.11" depd@2.0.0: version "2.0.0" @@ -1311,87 +1026,33 @@ dependency-graph@0.11.0, dependency-graph@~0.11.0: resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - dompurify@^2.2.8: - version "2.4.4" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.4.tgz#c17803931dd524e1b68e0e940a84567f9498f4bd" - integrity sha512-1e2SpqHiRx4DPvmRuXU5J0di3iQACwJM+mFGE2HAkkK7Tbnfk9WcghcAmyWc9CRrjyRRUpmuhPUH6LphQQR3EQ== - -dot-prop@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== - dependencies: - is-obj "^2.0.0" - -duplexer3@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" - integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== - -elliptic@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" + version "2.4.5" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.5.tgz#0e89a27601f0bad978f9a924e7a05d5d2cccdd87" + integrity sha512-jggCCd+8Iqp4Tsz0nIvpcb22InKEBrGz5dw3EQJMs8HPJDsKbFIO3STYtAvCfDx26Muevn1MHVI0XxjgFfmiSA== emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - eol@0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== es-abstract@^1.19.0, es-abstract@^1.20.4: - version "1.21.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.1.tgz#e6105a099967c08377830a0c9cb589d570dd86c6" - integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== dependencies: + array-buffer-byte-length "^1.0.0" available-typed-arrays "^1.0.5" call-bind "^1.0.2" es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" - function-bind "^1.1.1" function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" + get-intrinsic "^1.2.0" get-symbol-description "^1.0.0" globalthis "^1.0.3" gopd "^1.0.1" @@ -1399,8 +1060,8 @@ es-abstract@^1.19.0, es-abstract@^1.20.4: has-property-descriptors "^1.0.0" has-proto "^1.0.1" has-symbols "^1.0.3" - internal-slot "^1.0.4" - is-array-buffer "^3.0.1" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" is-callable "^1.2.7" is-negative-zero "^2.0.2" is-regex "^1.1.4" @@ -1408,11 +1069,12 @@ es-abstract@^1.19.0, es-abstract@^1.20.4: is-string "^1.0.7" is-typed-array "^1.1.10" is-weakref "^1.0.2" - object-inspect "^1.12.2" + object-inspect "^1.12.3" object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.4.3" safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" string.prototype.trimend "^1.0.6" string.prototype.trimstart "^1.0.6" typed-array-length "^1.0.4" @@ -1460,11 +1122,6 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-goat@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" - integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== - escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1517,19 +1174,6 @@ eventemitter3@^4.0.7: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -events@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - expected-node-version@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/expected-node-version/-/expected-node-version-1.0.2.tgz#b8d225b9bf676a9e87e06dbd615b52fc9d1e386b" @@ -1666,20 +1310,6 @@ get-source@^2.0.12: data-uri-to-buffer "^2.0.0" source-map "^0.6.1" -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -1726,13 +1356,6 @@ glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -global-dirs@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" - integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== - dependencies: - ini "2.0.0" - globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -1752,29 +1375,12 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -handlebars@^4.7.6, handlebars@^4.7.7: +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +handlebars@^4.7.6: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== @@ -1825,11 +1431,6 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has-yarn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" - integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== - has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -1837,32 +1438,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - hoist-non-react-statics@^3.0.0: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -1870,11 +1445,6 @@ hoist-non-react-statics@^3.0.0: dependencies: react-is "^16.7.0" -http-cache-semantics@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== - http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -1900,11 +1470,6 @@ http2-client@^1.2.5: resolved "https://registry.yarnpkg.com/http2-client/-/http2-client-1.3.5.tgz#20c9dc909e3cc98284dd20af2432c524086df181" integrity sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA== -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== - https-proxy-agent@5, https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -1920,25 +1485,10 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ieee754@^1.1.4: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - immer@^9.0.6: - version "9.0.19" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.19.tgz#67fb97310555690b5f9cd8380d38fc0aabb6b38b" - integrity sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ== - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + version "9.0.21" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" + integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== inflight@^1.0.4: version "1.0.6" @@ -1948,32 +1498,12 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.1: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== - -ini@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - -ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -internal-slot@^1.0.4: +internal-slot@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== @@ -1992,13 +1522,13 @@ ip@^2.0.0: resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== -is-array-buffer@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz#deb1db4fcae48308d54ef2442706c0393997052a" - integrity sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ== +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== dependencies: call-bind "^1.0.2" - get-intrinsic "^1.1.3" + get-intrinsic "^1.2.0" is-typed-array "^1.1.10" is-bigint@^1.0.1: @@ -2028,17 +1558,10 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-core-module@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== +is-core-module@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4" + integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== dependencies: has "^1.0.3" @@ -2066,24 +1589,11 @@ is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-installed-globally@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" - integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== - dependencies: - global-dirs "^3.0.0" - is-path-inside "^3.0.2" - is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== -is-npm@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" - integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== - is-number-object@^1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" @@ -2096,16 +1606,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-inside@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - is-reference@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" @@ -2153,11 +1653,6 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.9: gopd "^1.0.1" has-tostringtag "^1.0.0" -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== - is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -2165,26 +1660,11 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" -is-yarn-global@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" - integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== -isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - js-levenshtein@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" @@ -2212,11 +1692,6 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== - json-pointer@0.6.2, json-pointer@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/json-pointer/-/json-pointer-0.6.2.tgz#f97bd7550be5e9ea901f8c9264c9d436a22a93cd" @@ -2256,20 +1731,6 @@ jsonpointer@^5.0.0: resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -latest-version@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" - integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== - dependencies: - package-json "^6.3.0" - leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -2303,7 +1764,7 @@ lodash.topath@^4.5.2: resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009" integrity sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg== -lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.21, lodash@~4.17.21: +lodash@^4.17.14, lodash@^4.17.21, lodash@~4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -2315,16 +1776,6 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -2332,13 +1783,6 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - lunr@^2.3.9: version "2.3.9" resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" @@ -2351,31 +1795,15 @@ magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - mark.js@^8.11.1: version "8.11.1" resolved "https://registry.yarnpkg.com/mark.js/-/mark.js-8.11.1.tgz#180f1f9ebef8b0e638e4166ad52db879beb2ffc5" integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== marked@^4.0.15: - version "4.2.12" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.2.12.tgz#d69a64e21d71b06250da995dcd065c11083bebb5" - integrity sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw== - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== merge2@^1.3.0: version "1.4.1" @@ -2390,29 +1818,6 @@ micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - minimatch@3.1.2, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -2427,7 +1832,7 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: +minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -2439,15 +1844,10 @@ mkdirp@^0.5.6: dependencies: minimist "^1.2.6" -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - mobx-react-lite@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.4.0.tgz#d59156a96889cdadad751e5e4dab95f28926dfff" - integrity sha512-bRuZp3C0itgLKHu/VNxi66DN/XVkQG7xtoBVWxpvC5FhAqbOCP21+nPhULjnzEqd7xBMybp6KwytdUpZKEgpIQ== + version "3.4.3" + resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.4.3.tgz#3a4c22c30bfaa8b1b2aa48d12b2ba811c0947ab7" + integrity sha512-NkJREyFTSUXR772Qaai51BnE1voWx56LOL80xG7qkZr6vo8vEaLF3sz1JNUVh+rxmUzxYaqOhfuxTfqUh0FXUg== mobx-react@^7.2.0: version "7.6.0" @@ -2457,9 +1857,9 @@ mobx-react@^7.2.0: mobx-react-lite "^3.4.0" mobx@^6.3.2: - version "6.8.0" - resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.8.0.tgz#59051755fdb5c8a9f3f2e0a9b6abaf86bab7f843" - integrity sha512-+o/DrHa4zykFMSKfS8Z+CPSEg5LW9tSNGTuN8o6MF1GKxlfkSHSeJn5UtgxvPkGgaouplnrLXCF+duAsmm6FHQ== + version "6.9.0" + resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.9.0.tgz#8a894c26417c05bed2cf7499322e589ee9787397" + integrity sha512-HdKewQEREEJgsWnErClfbFoVebze6rGazxFLU/XUyrII8dORfVszN1V0BMRnQSzcgsNNtkX8DHj3nC6cdWE9YQ== ms@2.1.2: version "2.1.2" @@ -2508,35 +1908,6 @@ node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" -node-libs-browser@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - node-readfiles@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/node-readfiles/-/node-readfiles-0.2.0.tgz#dbbd4af12134e2e635c245ef93ffcf6f60673a5d" @@ -2549,11 +1920,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - oas-kit-common@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/oas-kit-common/-/oas-kit-common-1.0.8.tgz#6d8cacf6e9097967a4c7ea8bcbcbd77018e1f535" @@ -2605,7 +1971,7 @@ object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.12.2, object-inspect@^1.9.0: +object-inspect@^1.12.3, object-inspect@^1.9.0: version "1.12.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== @@ -2625,7 +1991,7 @@ object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -2652,16 +2018,6 @@ optionator@^0.8.1: type-check "~0.3.2" word-wrap "~1.2.3" -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - pac-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz#b718f76475a6a5415c2efbe256c1c971c84f635e" @@ -2686,37 +2042,6 @@ pac-resolver@^5.0.0: ip "^1.1.5" netmask "^2.0.2" -package-json@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" - integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== - dependencies: - got "^9.6.0" - registry-auth-token "^4.0.0" - registry-url "^5.0.0" - semver "^6.2.0" - -pako@~1.0.5: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - path-browserify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" @@ -2732,17 +2057,6 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -pbkdf2@^3.0.3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - perfect-scrollbar@^1.5.5: version "1.5.5" resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz#41a211a2fb52a7191eff301432134ea47052b27f" @@ -2789,11 +2103,6 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== - printable-characters@^1.0.42: version "1.0.42" resolved "https://registry.yarnpkg.com/printable-characters/-/printable-characters-1.0.42.tgz#3f18e977a9bd8eb37fcc4ff5659d7be90868b3d8" @@ -2804,16 +2113,6 @@ prismjs@^1.27.0: resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - prop-types@^15.5.0, prop-types@^15.7.2: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -2842,78 +2141,23 @@ proxy-from-env@^1.0.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - -punycode@^1.2.4: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== - punycode@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -pupa@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" - integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== - dependencies: - escape-goat "^2.0.0" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: +randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - raw-body@^2.2.0: version "2.5.2" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" @@ -2924,16 +2168,6 @@ raw-body@^2.2.0: iconv-lite "0.4.24" unpipe "1.0.0" -rc@1.2.8, rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - react-dom@^17.0.1: version "17.0.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" @@ -2974,23 +2208,10 @@ readable-stream@1.1.x: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.2, readable-stream@^2.3.3, readable-stream@^2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -3003,52 +2224,6 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -redoc-cli@^0.13.2: - version "0.13.20" - resolved "https://registry.yarnpkg.com/redoc-cli/-/redoc-cli-0.13.20.tgz#66a238f8dd6b6509e5475df81dddaa75ed9d1465" - integrity sha512-mmaJFyaAS+kzh2GwX7pi1x4K/zbQynJFv9S4mp3Ra5Rw611XxKjWmuVF3ccPV+TAGEe0rU3fYkMuOQg1pA8RWw== - dependencies: - chokidar "^3.5.1" - handlebars "^4.7.7" - isarray "^2.0.5" - mkdirp "^1.0.4" - mobx "^6.3.2" - node-libs-browser "^2.2.1" - react "^17.0.1" - react-dom "^17.0.1" - redoc "2.0.0-rc.77" - styled-components "^5.3.0" - update-notifier "^5.0.1" - yargs "^17.3.1" - -redoc@2.0.0-rc.77: - version "2.0.0-rc.77" - resolved "https://registry.yarnpkg.com/redoc/-/redoc-2.0.0-rc.77.tgz#bb1f46bfb65e08b59a58e23f2d7b272cf1f5a3cb" - integrity sha512-hiCMNSEl6R9vDkiVBMJSKxyT+wLY0qZdw+UZuOHWDCFm3uV0SELwTUU+spVBFCdzM4fdxjCnvsY2vX6cjcJNNg== - dependencies: - "@redocly/openapi-core" "^1.0.0-beta.104" - classnames "^2.3.1" - decko "^1.2.0" - dompurify "^2.2.8" - eventemitter3 "^4.0.7" - json-pointer "^0.6.2" - lunr "^2.3.9" - mark.js "^8.11.1" - marked "^4.0.15" - mobx-react "^7.2.0" - openapi-sampler "^1.3.0" - path-browserify "^1.0.1" - perfect-scrollbar "^1.5.5" - polished "^4.1.3" - prismjs "^1.27.0" - prop-types "^15.7.2" - react-tabs "^3.2.2" - slugify "~1.4.7" - stickyfill "^1.1.1" - style-loader "^3.3.1" - swagger2openapi "^7.0.6" - url-template "^2.0.8" - redoc@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/redoc/-/redoc-2.0.0.tgz#8b3047ca75b84d31558c6c92da7f84affef35c3e" @@ -3096,20 +2271,6 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" -registry-auth-token@^4.0.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" - integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== - dependencies: - rc "1.2.8" - -registry-url@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" - integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== - dependencies: - rc "^1.2.8" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -3126,34 +2287,19 @@ reserved@0.1.2: integrity sha512-/qO54MWj5L8WCBP9/UNe2iefJc+L9yETbH32xO/ft/EYPOTCR5k+azvDUgdCOKwZH8hXwPd0b8XBL78Nn2U69g== resolve@^1.17.0: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + version "1.22.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.3.tgz#4b4055349ffb962600972da1fdc33c46a4eb3283" + integrity sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.12.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== - dependencies: - lowercase-keys "^1.0.0" - reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - rollup@~2.79.0: version "2.79.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" @@ -3168,16 +2314,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - safe-regex-test@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" @@ -3192,7 +2333,7 @@ safe-stable-stringify@^1.1: resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz#c8a220ab525cd94e60ebf47ddc404d610dc5d84a" integrity sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw== -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: +"safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -3205,48 +2346,16 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" -semver-diff@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" - integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== - dependencies: - semver "^6.3.0" - semver@^5.0.3: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.4: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" - -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" @@ -3305,11 +2414,6 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.2: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - simple-eval@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/simple-eval/-/simple-eval-1.0.0.tgz#7ba8e6049840690b2d4e356ed01f13209e03aad1" @@ -3383,26 +2487,7 @@ stickyfill@^1.1.1: resolved "https://registry.yarnpkg.com/stickyfill/-/stickyfill-1.1.1.tgz#39413fee9d025c74a7e59ceecb23784cc0f17f02" integrity sha512-GCp7vHAfpao+Qh/3Flh9DXEJ/qSi0KJwJw6zYlZOtRYXWUIpMM6mC2rIep/dK8RQqwW0KxGJIllmjPIBOGN8AA== -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -3411,6 +2496,15 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2 is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimend@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" @@ -3429,7 +2523,7 @@ string.prototype.trimstart@^1.0.6: define-properties "^1.1.4" es-abstract "^1.20.4" -string_decoder@^1.0.0, string_decoder@^1.1.1: +string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -3441,13 +2535,6 @@ string_decoder@~0.10.x: resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - strip-ansi@6.0, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -3455,15 +2542,10 @@ strip-ansi@6.0, strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - style-loader@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" - integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== + version "3.3.2" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.2.tgz#eaebca714d9e462c19aa1e3599057bc363924899" + integrity sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw== styled-components@5.3.3: version "5.3.3" @@ -3481,22 +2563,6 @@ styled-components@5.3.3: shallowequal "^1.1.0" supports-color "^5.5.0" -styled-components@^5.3.0: - version "5.3.6" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.6.tgz#27753c8c27c650bee9358e343fc927966bfd00d1" - integrity sha512-hGTZquGAaTqhGWldX7hhfzjnIYBZ0IXQXkCYdvF1Sq3DsUaLx6+NTHC5Jj1ooM2F68sBiVz3lvhfwQs/S3l6qg== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/traverse" "^7.4.5" - "@emotion/is-prop-valid" "^1.1.0" - "@emotion/stylis" "^0.8.4" - "@emotion/unitless" "^0.7.4" - babel-plugin-styled-components ">= 1.12.0" - css-to-react-native "^3.0.0" - hoist-non-react-statics "^3.0.0" - shallowequal "^1.1.0" - supports-color "^5.5.0" - supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -3538,28 +2604,11 @@ text-table@0.2: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -timers-browserify@^2.0.4: - version "2.0.12" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" - integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== - dependencies: - setimmediate "^1.0.4" - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA== - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3587,11 +2636,6 @@ tslib@^2.0.1, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== - type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -3599,11 +2643,6 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - typed-array-length@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" @@ -3613,13 +2652,6 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - uglify-js@^3.1.4: version "3.17.4" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" @@ -3635,13 +2667,6 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -3652,26 +2677,6 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-notifier@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" - integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== - dependencies: - boxen "^5.0.0" - chalk "^4.1.0" - configstore "^5.0.1" - has-yarn "^2.1.0" - import-lazy "^2.1.0" - is-ci "^2.0.0" - is-installed-globally "^0.4.0" - is-npm "^5.0.0" - is-yarn-global "^0.3.0" - latest-version "^5.1.0" - pupa "^2.1.1" - semver "^7.3.4" - semver-diff "^3.1.1" - xdg-basedir "^4.0.0" - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -3684,45 +2689,16 @@ urijs@^1.19.11: resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== - dependencies: - prepend-http "^2.0.0" - url-template@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" integrity sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw== -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ== - dependencies: - inherits "2.0.1" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - utility-types@^3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" @@ -3735,15 +2711,10 @@ validate-npm-package-name@3.0.0: dependencies: builtins "^1.0.3" -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - -vm2@^3.9.8: - version "3.9.16" - resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.16.tgz#0fbc2a265f7bf8b837cea6f4a908f88a3f93b8e6" - integrity sha512-3T9LscojNTxdOyG+e8gFeyBXkMlOBYDoF6dqZbj+MPVHi9x10UfiTAJIobuchRCp3QvC+inybTbMJIUrLsig0w== +vm2@^3.9.11: + version "3.9.17" + resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.17.tgz#251b165ff8a0e034942b5181057305e39570aeab" + integrity sha512-AqwtCnZ/ERcX+AVj9vUsphY56YANXxRuqMb7GsDtAr0m0PcQX3u0Aj3KWiXM0YAHy7i6JEeHrwOnwXbGYgRpAw== dependencies: acorn "^8.7.0" acorn-walk "^8.2.0" @@ -3784,13 +2755,6 @@ which-typed-array@^1.1.9: has-tostringtag "^1.0.0" is-typed-array "^1.1.10" -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -3815,36 +2779,16 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - ws@^7.4.2: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== - xregexp@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" integrity sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA== -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -3855,11 +2799,6 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - yaml-ast-parser@0.0.43: version "0.0.43" resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" @@ -3906,7 +2845,7 @@ yargs@17.3.1: y18n "^5.0.5" yargs-parser "^21.0.0" -yargs@^17.0.1, yargs@^17.3.1: +yargs@^17.0.1: version "17.7.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== From c43f942cc59aa2687f60e7cdddf8212bf52a2987 Mon Sep 17 00:00:00 2001 From: Marc Frei Date: Fri, 12 May 2023 11:10:21 +0200 Subject: [PATCH 022/255] deps: replace inet.af/netaddr with net/netip and go4.org/netipx (#4313) Replace deprecated inet.af/netaddr with its standard library replacement package net/netip. Use go4.org/netipx for some the pieces that were not added to the standard library. This change does not affect the `snet` API, or any other public API. --- control/beaconing/BUILD.bazel | 1 - control/beaconing/originator.go | 2 +- control/beaconing/originator_test.go | 2 +- control/beaconing/propagator.go | 3 +- control/beaconing/propagator_test.go | 2 +- control/beaconing/writer_test.go | 6 +- control/cmd/control/BUILD.bazel | 2 +- control/cmd/control/main.go | 4 +- control/config/BUILD.bazel | 2 - control/config/drkey.go | 7 +- control/config/drkey_test.go | 6 +- control/drkey/grpc/BUILD.bazel | 3 +- control/drkey/grpc/drkey_service.go | 4 +- control/drkey/grpc/drkey_service_test.go | 72 +++++++++---------- control/ifstate/BUILD.bazel | 1 - control/ifstate/ifstate.go | 5 +- gateway/BUILD.bazel | 1 - gateway/control/BUILD.bazel | 2 +- gateway/control/grpc/BUILD.bazel | 1 - gateway/control/grpc/mock_grpc/BUILD.bazel | 1 - gateway/control/grpc/mock_grpc/mock.go | 6 +- gateway/control/grpc/prefix_server.go | 8 +-- gateway/control/prefixesfilter.go | 8 +-- gateway/gateway.go | 4 +- gateway/routing/BUILD.bazel | 3 +- gateway/routing/advertise.go | 11 +-- gateway/routing/export_test.go | 5 +- gateway/routing/ipset.go | 11 +-- gateway/routing/marshal.go | 7 +- gateway/routing/policy.go | 19 ++--- gateway/routing/policy_test.go | 4 +- go.mod | 4 +- go.sum | 10 +-- go_deps.bzl | 34 ++++----- licenses/data/org_go4_intern/LICENSE | 29 -------- .../LICENSE | 0 .../LICENSE | 29 -------- pkg/experimental/hiddenpath/BUILD.bazel | 1 - .../hiddenpath/beaconwriter_test.go | 6 +- pkg/private/xtest/BUILD.bazel | 1 - pkg/private/xtest/helpers.go | 10 +-- pkg/snet/BUILD.bazel | 1 - pkg/snet/udpaddr.go | 6 +- private/app/flag/BUILD.bazel | 2 - private/app/flag/env.go | 20 +++--- private/app/flag/env_test.go | 16 ++--- scion-pki/certs/renew.go | 2 +- scion/cmd/scion/ping.go | 2 +- scion/cmd/scion/showpaths.go | 3 +- scion/cmd/scion/traceroute.go | 2 +- 50 files changed, 152 insertions(+), 239 deletions(-) delete mode 100644 licenses/data/org_go4_intern/LICENSE rename licenses/data/{af_inet_netaddr => org_go4_netipx}/LICENSE (100%) delete mode 100644 licenses/data/org_go4_unsafe_assume_no_moving_gc/LICENSE diff --git a/control/beaconing/BUILD.bazel b/control/beaconing/BUILD.bazel index 515c9ef1c..d3123fdd6 100644 --- a/control/beaconing/BUILD.bazel +++ b/control/beaconing/BUILD.bazel @@ -78,7 +78,6 @@ go_test( "//private/segment/verifier/mock_verifier:go_default_library", "//private/topology:go_default_library", "//private/trust:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_golang_mock//gomock:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/control/beaconing/originator.go b/control/beaconing/originator.go index d8541c214..52997e72d 100644 --- a/control/beaconing/originator.go +++ b/control/beaconing/originator.go @@ -174,7 +174,7 @@ func (o *beaconOriginator) originateBeacon(ctx context.Context) error { senderCtx, topoInfo.IA, o.intf.TopoInfo().ID, - topoInfo.InternalAddr.UDPAddr(), + net.UDPAddrFromAddrPort(topoInfo.InternalAddr), ) if err != nil { o.incrementMetrics(labels.WithResult(prom.ErrNetwork)) diff --git a/control/beaconing/originator_test.go b/control/beaconing/originator_test.go index ac98015e2..3c9d78d1f 100644 --- a/control/beaconing/originator_test.go +++ b/control/beaconing/originator_test.go @@ -104,7 +104,7 @@ func TestOriginatorRun(t *testing.T) { // Check the interface matches. assert.Equal(t, hopF.ConsEgress, egIfId) // Check that the beacon is sent to the correct border router. - br := interfaceInfos(topo)[egIfId].InternalAddr.UDPAddr() + br := net.UDPAddrFromAddrPort(interfaceInfos(topo)[egIfId].InternalAddr) assert.Equal(t, br, nextHop) return nil }, diff --git a/control/beaconing/propagator.go b/control/beaconing/propagator.go index e3f24cb1c..f2d0e2719 100644 --- a/control/beaconing/propagator.go +++ b/control/beaconing/propagator.go @@ -16,6 +16,7 @@ package beaconing import ( "context" + "net" "sort" "strconv" "sync" @@ -266,7 +267,7 @@ func (p *propagator) Propagate(ctx context.Context) error { senderCtx, topoInfo.IA, egress, - topoInfo.InternalAddr.UDPAddr(), + net.UDPAddrFromAddrPort(topoInfo.InternalAddr), ) if err != nil { for _, b := range p.beacons { diff --git a/control/beaconing/propagator_test.go b/control/beaconing/propagator_test.go index d79d2c8c0..1bd1ea99e 100644 --- a/control/beaconing/propagator_test.go +++ b/control/beaconing/propagator_test.go @@ -293,6 +293,6 @@ func validateSend( // Check the interface matches. assert.Equal(t, hopF.ConsEgress, egIfId) // Check that the beacon is sent to the correct border router. - br := interfaceInfos(topo)[egIfId].InternalAddr.UDPAddr() + br := net.UDPAddrFromAddrPort(interfaceInfos(topo)[egIfId].InternalAddr) assert.Equal(t, br, nextHop) } diff --git a/control/beaconing/writer_test.go b/control/beaconing/writer_test.go index 69013e028..4613aa1e9 100644 --- a/control/beaconing/writer_test.go +++ b/control/beaconing/writer_test.go @@ -23,6 +23,7 @@ import ( "fmt" "hash" "net" + "net/netip" "sync" "testing" "time" @@ -30,7 +31,6 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "inet.af/netaddr" "github.com/scionproto/scion/control/beacon" "github.com/scionproto/scion/control/beaconing" @@ -259,7 +259,7 @@ func TestRegistrarRun(t *testing.T) { assert.Equal(t, pathHopField.ConsEgress, segHopField.ConsEgress) nextHop := pathHopField.ConsIngress - a := interfaceInfos(topo)[nextHop].InternalAddr.UDPAddr() + a := net.UDPAddrFromAddrPort(interfaceInfos(topo)[nextHop].InternalAddr) assert.Equal(t, a, s.Addr.NextHop) } }) @@ -371,7 +371,7 @@ func interfaceInfos(topo topology.Topology) map[uint16]ifstate.InterfaceInfo { ID: uint16(info.ID), IA: info.IA, LinkType: info.LinkType, - InternalAddr: netaddr.MustParseIPPort(info.InternalAddr.String()), + InternalAddr: netip.MustParseAddrPort(info.InternalAddr.String()), RemoteID: uint16(info.RemoteIFID), MTU: uint16(info.MTU), } diff --git a/control/cmd/control/BUILD.bazel b/control/cmd/control/BUILD.bazel index bdb3b6307..ad9a6938a 100644 --- a/control/cmd/control/BUILD.bazel +++ b/control/cmd/control/BUILD.bazel @@ -68,12 +68,12 @@ go_library( "//private/trust/compat:go_default_library", "//private/trust/grpc:go_default_library", "//private/trust/metrics:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_go_chi_chi_v5//:go_default_library", "@com_github_go_chi_cors//:go_default_library", "@com_github_grpc_ecosystem_go_grpc_prometheus//:go_default_library", "@com_github_spf13_cobra//:go_default_library", "@in_gopkg_yaml_v2//:go_default_library", + "@org_go4_netipx//:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//health:go_default_library", "@org_golang_google_grpc//health/grpc_health_v1:go_default_library", diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index 2f53c2ca9..d481cd607 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -32,11 +32,11 @@ import ( "github.com/go-chi/cors" promgrpc "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/spf13/cobra" + "go4.org/netipx" "golang.org/x/sync/errgroup" "google.golang.org/grpc" "google.golang.org/grpc/health" healthpb "google.golang.org/grpc/health/grpc_health_v1" - "inet.af/netaddr" cs "github.com/scionproto/scion/control" "github.com/scionproto/scion/control/beacon" @@ -834,7 +834,7 @@ func createBeaconStore( func adaptInterfaceMap(in map[common.IFIDType]topology.IFInfo) map[uint16]ifstate.InterfaceInfo { converted := make(map[uint16]ifstate.InterfaceInfo, len(in)) for id, info := range in { - addr, ok := netaddr.FromStdAddr( + addr, ok := netipx.FromStdAddr( info.InternalAddr.IP, info.InternalAddr.Port, info.InternalAddr.Zone, diff --git a/control/config/BUILD.bazel b/control/config/BUILD.bazel index dfff0ea96..97e2c636e 100644 --- a/control/config/BUILD.bazel +++ b/control/config/BUILD.bazel @@ -22,7 +22,6 @@ go_library( "//private/mgmtapi/jwtauth:go_default_library", "//private/storage:go_default_library", "//private/trust/config:go_default_library", - "@af_inet_netaddr//:go_default_library", ], ) @@ -41,7 +40,6 @@ go_test( "//private/mgmtapi/mgmtapitest:go_default_library", "//private/storage:go_default_library", "//private/storage/test:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_pelletier_go_toml//:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/control/config/drkey.go b/control/config/drkey.go index 7dbdcdcdb..38ad9f776 100644 --- a/control/config/drkey.go +++ b/control/config/drkey.go @@ -16,11 +16,10 @@ package config import ( "io" + "net/netip" "strings" "time" - "inet.af/netaddr" - "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/serrors" @@ -138,7 +137,7 @@ func (cfg *SecretValueHostList) ConfigName() string { } type HostProto struct { - Host netaddr.IP + Host netip.Addr Proto drkey.Protocol } @@ -147,7 +146,7 @@ func (cfg *SecretValueHostList) ToAllowedSet() map[HostProto]struct{} { m := make(map[HostProto]struct{}) for proto, ipList := range *cfg { for _, ip := range ipList { - host, err := netaddr.ParseIP(ip) + host, err := netip.ParseAddr(ip) if err != nil { continue } diff --git a/control/config/drkey_test.go b/control/config/drkey_test.go index b127a07b6..4c1a4ac62 100644 --- a/control/config/drkey_test.go +++ b/control/config/drkey_test.go @@ -16,13 +16,13 @@ package config import ( "bytes" + "net/netip" "os" "testing" toml "github.com/pelletier/go-toml" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "inet.af/netaddr" "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/private/storage" @@ -107,9 +107,9 @@ func TestSecretValueHostListSyntax(t *testing.T) { func TestToMapPerHost(t *testing.T) { var cfg SecretValueHostList sample := `scmp = ["1.1.1.1", "2.2.2.2"]` - ip1111, err := netaddr.ParseIP("1.1.1.1") + ip1111, err := netip.ParseAddr("1.1.1.1") require.NoError(t, err) - ip2222, err := netaddr.ParseIP("2.2.2.2") + ip2222, err := netip.ParseAddr("2.2.2.2") require.NoError(t, err) err = toml.NewDecoder(bytes.NewReader([]byte(sample))).Strict(true).Decode(&cfg) require.NoError(t, err) diff --git a/control/drkey/grpc/BUILD.bazel b/control/drkey/grpc/BUILD.bazel index eef4d1bcb..9eb9cdef7 100644 --- a/control/drkey/grpc/BUILD.bazel +++ b/control/drkey/grpc/BUILD.bazel @@ -21,7 +21,7 @@ go_library( "//pkg/proto/drkey:go_default_library", "//pkg/scrypto/cppki:go_default_library", "//pkg/snet:go_default_library", - "@af_inet_netaddr//:go_default_library", + "@org_go4_netipx//:go_default_library", "@org_golang_google_grpc//credentials:go_default_library", "@org_golang_google_grpc//peer:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", @@ -54,7 +54,6 @@ go_test( "//private/trust:go_default_library", "//private/trust/mock_trust:go_default_library", "//scion-pki/testcrypto:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_golang_mock//gomock:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/control/drkey/grpc/drkey_service.go b/control/drkey/grpc/drkey_service.go index 23ca58692..b0a7278c2 100644 --- a/control/drkey/grpc/drkey_service.go +++ b/control/drkey/grpc/drkey_service.go @@ -19,10 +19,10 @@ import ( "crypto/x509" "net" + "go4.org/netipx" "google.golang.org/grpc/credentials" "google.golang.org/grpc/peer" "google.golang.org/protobuf/types/known/timestamppb" - "inet.af/netaddr" "github.com/scionproto/scion/control/config" "github.com/scionproto/scion/pkg/addr" @@ -263,7 +263,7 @@ func (d *Server) validateAllowedHost(protoId drkey.Protocol, peerAddr net.Addr) return serrors.New("invalid peer address type, expected *net.TCPAddr", "peer", peerAddr, "type", common.TypeOf(peerAddr)) } - localAddr, ok := netaddr.FromStdIP(tcpAddr.IP) + localAddr, ok := netipx.FromStdIP(tcpAddr.IP) if !ok { return serrors.New("unable to parse IP", "addr", tcpAddr.IP.String()) } diff --git a/control/drkey/grpc/drkey_service_test.go b/control/drkey/grpc/drkey_service_test.go index f70bc9f49..d9690769b 100644 --- a/control/drkey/grpc/drkey_service_test.go +++ b/control/drkey/grpc/drkey_service_test.go @@ -17,13 +17,13 @@ package grpc_test import ( "context" "net" + "net/netip" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "google.golang.org/grpc/peer" "google.golang.org/protobuf/types/known/timestamppb" - "inet.af/netaddr" "github.com/scionproto/scion/control/config" dk_grpc "github.com/scionproto/scion/control/drkey/grpc" @@ -39,8 +39,8 @@ import ( var ( ia111 = xtest.MustParseIA("1-ff00:0:111") ia112 = xtest.MustParseIA("1-ff00:0:112") - tcpHost1 = netaddr.MustParseIPPort("127.0.0.1:12345") - tcpHost2 = netaddr.MustParseIPPort("127.0.0.2:12345") + tcpHost1 = netip.MustParseAddrPort("127.0.0.1:12345") + tcpHost2 = netip.MustParseAddrPort("127.0.0.2:12345") ) var _ cppb.DRKeyInterServiceServer = &dk_grpc.Server{} @@ -64,11 +64,11 @@ func TestDRKeySV(t *testing.T) { }{ "allowed host": { ctx: peer.NewContext(context.Background(), &peer.Peer{ - Addr: tcpHost1.TCPAddr(), + Addr: net.TCPAddrFromAddrPort(tcpHost1), }), list: map[config.HostProto]struct{}{ { - Host: tcpHost1.IP(), + Host: tcpHost1.Addr(), Proto: drkey.SCMP, }: {}, }, @@ -81,11 +81,11 @@ func TestDRKeySV(t *testing.T) { }, "not allowed host": { ctx: peer.NewContext(context.Background(), &peer.Peer{ - Addr: tcpHost2.TCPAddr(), + Addr: net.TCPAddrFromAddrPort(tcpHost2), }), list: map[config.HostProto]struct{}{ { - Host: tcpHost1.IP(), + Host: tcpHost1.Addr(), Proto: drkey.SCMP, }: {}, }, @@ -121,7 +121,7 @@ func TestValidateASHost(t *testing.T) { assertErr assert.ErrorAssertionFunc }{ "no host": { - peerAddr: tcpHost1.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost1), req: drkey.ASHostMeta{ SrcIA: ia111, DstIA: ia112, @@ -130,30 +130,30 @@ func TestValidateASHost(t *testing.T) { assertErr: assert.Error, }, "no localIA": { - peerAddr: tcpHost1.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost1), req: drkey.ASHostMeta{ SrcIA: ia111, DstIA: ia112, - DstHost: tcpHost1.IP().String(), + DstHost: tcpHost1.Addr().String(), }, assertErr: assert.Error, }, "mismatch addr": { - peerAddr: tcpHost1.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost1), req: drkey.ASHostMeta{ SrcIA: ia111, DstIA: ia112, - DstHost: tcpHost2.IP().String(), + DstHost: tcpHost2.Addr().String(), }, LocalIA: ia112, assertErr: assert.Error, }, "valid host": { - peerAddr: tcpHost2.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost2), req: drkey.ASHostMeta{ SrcIA: ia111, DstIA: ia112, - DstHost: tcpHost2.IP().String(), + DstHost: tcpHost2.Addr().String(), }, LocalIA: ia112, assertErr: assert.NoError, @@ -177,7 +177,7 @@ func TestValidateHostASReq(t *testing.T) { assertErr assert.ErrorAssertionFunc }{ "no host": { - peerAddr: tcpHost1.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost1), req: drkey.HostASMeta{ SrcIA: ia111, DstIA: ia112, @@ -186,16 +186,16 @@ func TestValidateHostASReq(t *testing.T) { assertErr: assert.Error, }, "no localIA": { - peerAddr: tcpHost1.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost1), req: drkey.HostASMeta{ SrcIA: ia111, DstIA: ia112, - SrcHost: tcpHost1.IP().String(), + SrcHost: tcpHost1.Addr().String(), }, assertErr: assert.Error, }, "mismatch addr": { - peerAddr: tcpHost2.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost2), req: drkey.HostASMeta{ SrcIA: ia111, DstIA: ia112, @@ -205,11 +205,11 @@ func TestValidateHostASReq(t *testing.T) { assertErr: assert.Error, }, "valid src": { - peerAddr: tcpHost1.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost1), req: drkey.HostASMeta{ SrcIA: ia111, DstIA: ia112, - SrcHost: tcpHost1.IP().String(), + SrcHost: tcpHost1.Addr().String(), }, LocalIA: ia111, assertErr: assert.NoError, @@ -233,7 +233,7 @@ func TestValidateHostHostReq(t *testing.T) { assertErr assert.ErrorAssertionFunc }{ "no host": { - peerAddr: tcpHost1.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost1), req: drkey.HostHostMeta{ SrcIA: ia111, DstIA: ia112, @@ -242,44 +242,44 @@ func TestValidateHostHostReq(t *testing.T) { assertErr: assert.Error, }, "no localIA": { - peerAddr: tcpHost1.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost1), req: drkey.HostHostMeta{ SrcIA: ia111, DstIA: ia112, - SrcHost: tcpHost1.IP().String(), - DstHost: tcpHost2.IP().String(), + SrcHost: tcpHost1.Addr().String(), + DstHost: tcpHost2.Addr().String(), }, assertErr: assert.Error, }, "mismatch addr": { - peerAddr: tcpHost2.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost2), req: drkey.HostHostMeta{ SrcIA: ia111, DstIA: ia112, - SrcHost: tcpHost1.IP().String(), - DstHost: tcpHost2.IP().String(), + SrcHost: tcpHost1.Addr().String(), + DstHost: tcpHost2.Addr().String(), }, LocalIA: ia111, assertErr: assert.Error, }, "valid src": { - peerAddr: tcpHost1.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost1), req: drkey.HostHostMeta{ SrcIA: ia111, DstIA: ia112, - SrcHost: tcpHost1.IP().String(), - DstHost: tcpHost2.IP().String(), + SrcHost: tcpHost1.Addr().String(), + DstHost: tcpHost2.Addr().String(), }, LocalIA: ia111, assertErr: assert.NoError, }, "valid dst": { - peerAddr: tcpHost2.TCPAddr(), + peerAddr: net.TCPAddrFromAddrPort(tcpHost2), req: drkey.HostHostMeta{ SrcIA: ia111, DstIA: ia112, - SrcHost: tcpHost1.IP().String(), - DstHost: tcpHost2.IP().String(), + SrcHost: tcpHost1.Addr().String(), + DstHost: tcpHost2.Addr().String(), }, LocalIA: ia112, assertErr: assert.NoError, @@ -321,7 +321,7 @@ func TestASHost(t *testing.T) { Engine: engine, } remotePeer := peer.Peer{ - Addr: tcpHost1.TCPAddr(), + Addr: net.TCPAddrFromAddrPort(tcpHost1), } request := &cppb.DRKeyASHostRequest{ ProtocolId: 200, @@ -352,7 +352,7 @@ func TestHostAS(t *testing.T) { Engine: engine, } remotePeer := peer.Peer{ - Addr: tcpHost1.TCPAddr(), + Addr: net.TCPAddrFromAddrPort(tcpHost1), } request := &cppb.DRKeyHostASRequest{ ProtocolId: 200, @@ -383,7 +383,7 @@ func TestHostHost(t *testing.T) { Engine: engine, } remotePeer := peer.Peer{ - Addr: tcpHost1.TCPAddr(), + Addr: net.TCPAddrFromAddrPort(tcpHost1), } request := &cppb.DRKeyHostHostRequest{ ProtocolId: 200, diff --git a/control/ifstate/BUILD.bazel b/control/ifstate/BUILD.bazel index df10c5119..cbd905418 100644 --- a/control/ifstate/BUILD.bazel +++ b/control/ifstate/BUILD.bazel @@ -11,7 +11,6 @@ go_library( deps = [ "//pkg/addr:go_default_library", "//private/topology:go_default_library", - "@af_inet_netaddr//:go_default_library", ], ) diff --git a/control/ifstate/ifstate.go b/control/ifstate/ifstate.go index f43b7133e..5fa04e4fa 100644 --- a/control/ifstate/ifstate.go +++ b/control/ifstate/ifstate.go @@ -15,11 +15,10 @@ package ifstate import ( + "net/netip" "sync" "time" - "inet.af/netaddr" - "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/private/topology" ) @@ -32,7 +31,7 @@ type InterfaceInfo struct { LinkType topology.LinkType // InternalAddr is the AS-internal address of the router that owns this // interface. - InternalAddr netaddr.IPPort + InternalAddr netip.AddrPort // RemoteID is the remote interface ID. RemoteID uint16 // MTU is the SCION MTU supported on this interface. diff --git a/gateway/BUILD.bazel b/gateway/BUILD.bazel index c15e42638..20a9406fb 100644 --- a/gateway/BUILD.bazel +++ b/gateway/BUILD.bazel @@ -38,7 +38,6 @@ go_library( "//private/service:go_default_library", "//private/svc:go_default_library", "//private/worker:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_lucas_clemente_quic_go//:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", diff --git a/gateway/control/BUILD.bazel b/gateway/control/BUILD.bazel index f00b574b0..d574dcb61 100644 --- a/gateway/control/BUILD.bazel +++ b/gateway/control/BUILD.bazel @@ -36,10 +36,10 @@ go_library( "//pkg/snet:go_default_library", "//private/path/pathpol:go_default_library", "//private/worker:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_google_gopacket//:go_default_library", "@com_github_google_gopacket//layers:go_default_library", "@com_github_olekukonko_tablewriter//:go_default_library", + "@org_go4_netipx//:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) diff --git a/gateway/control/grpc/BUILD.bazel b/gateway/control/grpc/BUILD.bazel index 90bf20e99..b020d0a8a 100644 --- a/gateway/control/grpc/BUILD.bazel +++ b/gateway/control/grpc/BUILD.bazel @@ -22,7 +22,6 @@ go_library( "//pkg/proto/gateway:go_default_library", "//pkg/snet:go_default_library", "//pkg/sock/reliable:go_default_library", - "@af_inet_netaddr//:go_default_library", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//peer:go_default_library", "@org_golang_google_grpc//status:go_default_library", diff --git a/gateway/control/grpc/mock_grpc/BUILD.bazel b/gateway/control/grpc/mock_grpc/BUILD.bazel index f22bc97ea..ba9de3668 100644 --- a/gateway/control/grpc/mock_grpc/BUILD.bazel +++ b/gateway/control/grpc/mock_grpc/BUILD.bazel @@ -16,7 +16,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/addr:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_golang_mock//gomock:go_default_library", ], ) diff --git a/gateway/control/grpc/mock_grpc/mock.go b/gateway/control/grpc/mock_grpc/mock.go index 13418bf5d..4a00edcf0 100644 --- a/gateway/control/grpc/mock_grpc/mock.go +++ b/gateway/control/grpc/mock_grpc/mock.go @@ -5,11 +5,11 @@ package mock_grpc import ( + netip "net/netip" reflect "reflect" gomock "github.com/golang/mock/gomock" addr "github.com/scionproto/scion/pkg/addr" - netaddr "inet.af/netaddr" ) // MockAdvertiser is a mock of Advertiser interface. @@ -36,10 +36,10 @@ func (m *MockAdvertiser) EXPECT() *MockAdvertiserMockRecorder { } // AdvertiseList mocks base method. -func (m *MockAdvertiser) AdvertiseList(arg0, arg1 addr.IA) ([]netaddr.IPPrefix, error) { +func (m *MockAdvertiser) AdvertiseList(arg0, arg1 addr.IA) ([]netip.Prefix, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AdvertiseList", arg0, arg1) - ret0, _ := ret[0].([]netaddr.IPPrefix) + ret0, _ := ret[0].([]netip.Prefix) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/gateway/control/grpc/prefix_server.go b/gateway/control/grpc/prefix_server.go index e53f8607c..421af0761 100644 --- a/gateway/control/grpc/prefix_server.go +++ b/gateway/control/grpc/prefix_server.go @@ -16,11 +16,11 @@ package grpc import ( "context" + "net/netip" "google.golang.org/grpc/codes" "google.golang.org/grpc/peer" "google.golang.org/grpc/status" - "inet.af/netaddr" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/metrics" @@ -30,7 +30,7 @@ import ( // Advertiser returns a list of IP prefixes to advertise. type Advertiser interface { - AdvertiseList(from, to addr.IA) ([]netaddr.IPPrefix, error) + AdvertiseList(from, to addr.IA) ([]netip.Prefix, error) } // IPPrefixServer serves IP prefix requests. @@ -68,7 +68,7 @@ func (s IPPrefixServer) Prefixes(ctx context.Context, continue } pb = append(pb, &gpb.Prefix{ - Prefix: canonicalIP(prefix.IP()), + Prefix: canonicalIP(prefix.Addr()), Mask: uint32(prefix.Bits()), }) } @@ -77,7 +77,7 @@ func (s IPPrefixServer) Prefixes(ctx context.Context, }, nil } -func canonicalIP(ip netaddr.IP) []byte { +func canonicalIP(ip netip.Addr) []byte { if ip.Is4() { a4 := ip.As4() return append([]byte(nil), a4[:]...) diff --git a/gateway/control/prefixesfilter.go b/gateway/control/prefixesfilter.go index 03f744df8..3ac09833e 100644 --- a/gateway/control/prefixesfilter.go +++ b/gateway/control/prefixesfilter.go @@ -17,7 +17,7 @@ package control import ( "net" - "inet.af/netaddr" + "go4.org/netipx" "github.com/scionproto/scion/gateway/routing" "github.com/scionproto/scion/pkg/addr" @@ -62,11 +62,11 @@ func (f PrefixesFilter) Prefixes( if rp == nil { return nil } - var sb netaddr.IPSetBuilder + var sb netipx.IPSetBuilder allowedCount := 0 rejectedCount := 0 for _, prefix := range prefixes { - p, ok := netaddr.FromStdIPNet(prefix) + p, ok := netipx.FromStdIPNet(prefix) if !ok { return serrors.New("can not convert prefix", "prefix", prefix) } @@ -92,7 +92,7 @@ func (f PrefixesFilter) Prefixes( } var allowedPrefixes []*net.IPNet for _, prefix := range set.Prefixes() { - allowedPrefixes = append(allowedPrefixes, prefix.IPNet()) + allowedPrefixes = append(allowedPrefixes, netipx.PrefixIPNet(prefix)) } return f.Consumer.Prefixes(remote, gateway, allowedPrefixes) } diff --git a/gateway/gateway.go b/gateway/gateway.go index bdd994d5d..14103af34 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -19,6 +19,7 @@ import ( "encoding/json" "net" "net/http" + "net/netip" "os" "strconv" "time" @@ -26,7 +27,6 @@ import ( quic "github.com/lucas-clemente/quic-go" "github.com/prometheus/client_golang/prometheus" "google.golang.org/grpc" - "inet.af/netaddr" "github.com/scionproto/scion/gateway/control" controlgrpc "github.com/scionproto/scion/gateway/control/grpc" @@ -156,7 +156,7 @@ type SelectAdvertisedRoutes struct { ConfigPublisher *control.ConfigPublisher } -func (a *SelectAdvertisedRoutes) AdvertiseList(from, to addr.IA) ([]netaddr.IPPrefix, error) { +func (a *SelectAdvertisedRoutes) AdvertiseList(from, to addr.IA) ([]netip.Prefix, error) { return routing.AdvertiseList(a.ConfigPublisher.RoutingPolicy(), from, to) } diff --git a/gateway/routing/BUILD.bazel b/gateway/routing/BUILD.bazel index 832377c1f..be44c3ae8 100644 --- a/gateway/routing/BUILD.bazel +++ b/gateway/routing/BUILD.bazel @@ -16,7 +16,7 @@ go_library( deps = [ "//pkg/addr:go_default_library", "//pkg/private/serrors:go_default_library", - "@af_inet_netaddr//:go_default_library", + "@org_go4_netipx//:go_default_library", ], ) @@ -36,7 +36,6 @@ go_test( "//gateway/routing/mock_routing:go_default_library", "//pkg/addr:go_default_library", "//pkg/private/xtest:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_golang_mock//gomock:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/gateway/routing/advertise.go b/gateway/routing/advertise.go index 01b47c5fc..36f252aa6 100644 --- a/gateway/routing/advertise.go +++ b/gateway/routing/advertise.go @@ -16,19 +16,20 @@ package routing import ( "net" + "net/netip" - "inet.af/netaddr" + "go4.org/netipx" "github.com/scionproto/scion/pkg/addr" ) // AdvertiseList returns the list of prefixes to advertise for the given policy // and ISD-ASes. -func AdvertiseList(pol *Policy, from, to addr.IA) ([]netaddr.IPPrefix, error) { +func AdvertiseList(pol *Policy, from, to addr.IA) ([]netip.Prefix, error) { if pol == nil { - return []netaddr.IPPrefix{}, nil + return []netip.Prefix{}, nil } - var nets []netaddr.IPPrefix + var nets []netip.Prefix for _, r := range pol.Rules { if r.Action != Advertise || !r.From.Match(from) || !r.To.Match(to) { continue @@ -56,7 +57,7 @@ func StaticAdvertised(pol *Policy) []*net.IPNet { continue } for _, prefix := range r.Network.Allowed { - nets = append(nets, prefix.IPNet()) + nets = append(nets, netipx.PrefixIPNet(prefix)) } } return nets diff --git a/gateway/routing/export_test.go b/gateway/routing/export_test.go index 842900441..9f54dbf9c 100644 --- a/gateway/routing/export_test.go +++ b/gateway/routing/export_test.go @@ -15,11 +15,10 @@ package routing import ( + "net/netip" "strings" "testing" - "inet.af/netaddr" - "github.com/scionproto/scion/pkg/private/xtest" ) @@ -50,7 +49,7 @@ func NewNetworkMatcher(t *testing.T, networks string) NetworkMatcher { } matcher := NetworkMatcher{Negated: negated} for _, network := range strings.Split(networks, ",") { - matcher.Allowed = append(matcher.Allowed, netaddr.MustParseIPPrefix(network)) + matcher.Allowed = append(matcher.Allowed, netip.MustParsePrefix(network)) } return matcher } diff --git a/gateway/routing/ipset.go b/gateway/routing/ipset.go index 3f41251b0..9e052c088 100644 --- a/gateway/routing/ipset.go +++ b/gateway/routing/ipset.go @@ -15,24 +15,25 @@ package routing import ( + "net/netip" "strings" - "inet.af/netaddr" + "go4.org/netipx" ) -// IPSet is the same as netaddr.IPSet except that it can be converted to/from string. +// IPSet is the same as netipx.IPSet except that it can be converted to/from string. type IPSet struct { - netaddr.IPSet + netipx.IPSet } func ParseIPSet(s string) (IPSet, error) { - var sb netaddr.IPSetBuilder + var sb netipx.IPSetBuilder prefixes := strings.Split(s, ",") for _, prefix := range prefixes { if prefix == "" { continue } - p, err := netaddr.ParseIPPrefix(prefix) + p, err := netip.ParsePrefix(prefix) if err != nil { return IPSet{}, err } diff --git a/gateway/routing/marshal.go b/gateway/routing/marshal.go index 654962284..5b59ec3a8 100644 --- a/gateway/routing/marshal.go +++ b/gateway/routing/marshal.go @@ -19,11 +19,10 @@ import ( "bytes" "fmt" "net" + "net/netip" "strings" "text/tabwriter" - "inet.af/netaddr" - "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/serrors" ) @@ -147,9 +146,9 @@ func parseNetworkMatcher(b []byte) (NetworkMatcher, error) { negative = true b = b[1:] } - var networks []netaddr.IPPrefix + var networks []netip.Prefix for _, network := range bytes.Split(b, []byte(",")) { - n, err := netaddr.ParseIPPrefix(string(network)) + n, err := netip.ParsePrefix(string(network)) if err != nil { return NetworkMatcher{}, serrors.WrapStr("parsing network", err) } diff --git a/gateway/routing/policy.go b/gateway/routing/policy.go index f577cf9c1..17c5f8a07 100644 --- a/gateway/routing/policy.go +++ b/gateway/routing/policy.go @@ -18,9 +18,10 @@ import ( "crypto/sha256" "fmt" "net" + "net/netip" "strings" - "inet.af/netaddr" + "go4.org/netipx" "github.com/scionproto/scion/pkg/addr" ) @@ -71,12 +72,12 @@ func (p Policy) Digest() []byte { } // Match matches an IP range to the policy and returns the subranges that satisfy it. -func (p Policy) Match(from, to addr.IA, ipPrefix netaddr.IPPrefix) (IPSet, error) { +func (p Policy) Match(from, to addr.IA, ipPrefix netip.Prefix) (IPSet, error) { // Compile the rules into a set of allowed addresses. - var sb netaddr.IPSetBuilder + var sb netipx.IPSetBuilder if p.DefaultAction == Accept { - sb.AddPrefix(netaddr.MustParseIPPrefix("0.0.0.0/0")) - sb.AddPrefix(netaddr.MustParseIPPrefix("::/0")) + sb.AddPrefix(netip.MustParsePrefix("0.0.0.0/0")) + sb.AddPrefix(netip.MustParsePrefix("::/0")) } for i := len(p.Rules) - 1; i >= 0; i-- { rule := p.Rules[i] @@ -95,7 +96,7 @@ func (p Policy) Match(from, to addr.IA, ipPrefix netaddr.IPPrefix) (IPSet, error } } // Intersect the supplied IP range with the allowed range to get the result. - var nb netaddr.IPSetBuilder + var nb netipx.IPSetBuilder nb.AddPrefix(ipPrefix) ns, err := nb.IPSet() if err != nil { @@ -126,13 +127,13 @@ type IAMatcher interface { // NetworkMatcher matches IP networks. type NetworkMatcher struct { - Allowed []netaddr.IPPrefix + Allowed []netip.Prefix Negated bool } // IPSet returns a set containing all IPs allowed by the matcher. -func (m NetworkMatcher) IPSet() (*netaddr.IPSet, error) { - var sb netaddr.IPSetBuilder +func (m NetworkMatcher) IPSet() (*netipx.IPSet, error) { + var sb netipx.IPSetBuilder for _, prefix := range m.Allowed { sb.AddPrefix(prefix) } diff --git a/gateway/routing/policy_test.go b/gateway/routing/policy_test.go index 194f7df72..3a4171b00 100644 --- a/gateway/routing/policy_test.go +++ b/gateway/routing/policy_test.go @@ -15,11 +15,11 @@ package routing_test import ( + "net/netip" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "inet.af/netaddr" "github.com/scionproto/scion/gateway/routing" "github.com/scionproto/scion/pkg/private/xtest" @@ -201,7 +201,7 @@ func TestNetworkMatch(t *testing.T) { To: iaMatcher, } } - out, err := tc.policy.Match(ia, ia, netaddr.MustParseIPPrefix(tc.in)) + out, err := tc.policy.Match(ia, ia, netip.MustParsePrefix(tc.in)) assert.NoError(t, err) assert.Equal(t, tc.out, out.String()) }) diff --git a/go.mod b/go.mod index ab01fd8f9..dda75b54f 100644 --- a/go.mod +++ b/go.mod @@ -41,6 +41,7 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 go.uber.org/goleak v1.2.1 go.uber.org/zap v1.24.0 + go4.org/netipx v0.0.0-20230125063823-8449b0a6169f golang.org/x/crypto v0.6.0 golang.org/x/net v0.7.0 golang.org/x/sync v0.1.0 @@ -49,7 +50,6 @@ require ( google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 google.golang.org/protobuf v1.28.1 gopkg.in/yaml.v2 v2.4.0 - inet.af/netaddr v0.0.0-20220811202034-502d2d690317 ) require ( @@ -107,8 +107,6 @@ require ( github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect - go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect - go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/mod v0.8.0 // indirect golang.org/x/sys v0.5.0 // indirect diff --git a/go.sum b/go.sum index c8e8da25e..b77723de2 100644 --- a/go.sum +++ b/go.sum @@ -95,7 +95,6 @@ github.com/docker/cli v20.10.20+incompatible h1:lWQbHSHUFs7KraSN2jOJK7zbMS2jNCHI github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/docker v20.10.20+incompatible h1:kH9tx6XO+359d+iAkumyKDc5Q1kOwPuAUaeri48nD6E= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= -github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -453,11 +452,8 @@ go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95a go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE= -go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 h1:FyBZqvoA/jbNzuAWLQE2kG820zMAkcilx6BMjGbL/E4= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= +go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= +go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -835,8 +831,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -inet.af/netaddr v0.0.0-20220811202034-502d2d690317 h1:U2fwK6P2EqmopP/hFLTOAjWTki0qgd4GMJn5X8wOleU= -inet.af/netaddr v0.0.0-20220811202034-502d2d690317/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/go_deps.bzl b/go_deps.bzl index 4de35e40d..af2ee7998 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -7,17 +7,11 @@ load("@bazel_gazelle//:deps.bzl", "go_repository") def go_deps(): - go_repository( - name = "af_inet_netaddr", - importpath = "inet.af/netaddr", - sum = "h1:U2fwK6P2EqmopP/hFLTOAjWTki0qgd4GMJn5X8wOleU=", - version = "v0.0.0-20220811202034-502d2d690317", - ) go_repository( name = "co_honnef_go_tools", importpath = "honnef.co/go/tools", - sum = "h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=", - version = "v0.0.1-2020.1.4", + sum = "h1:ytYb4rOqyp1TSa2EPvNVwtPQJctSELKaMyLfqNP4+34=", + version = "v0.3.2", ) go_repository( name = "com_github_alecthomas_template", @@ -88,8 +82,8 @@ def go_deps(): go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", - sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=", - version = "v0.3.1", + sum = "h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=", + version = "v0.4.1", ) go_repository( name = "com_github_burntsushi_xgb", @@ -2037,16 +2031,10 @@ def go_deps(): version = "v1.3.0", ) go_repository( - name = "org_go4_intern", - importpath = "go4.org/intern", - sum = "h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE=", - version = "v0.0.0-20211027215823-ae77deb06f29", - ) - go_repository( - name = "org_go4_unsafe_assume_no_moving_gc", - importpath = "go4.org/unsafe/assume-no-moving-gc", - sum = "h1:FyBZqvoA/jbNzuAWLQE2kG820zMAkcilx6BMjGbL/E4=", - version = "v0.0.0-20220617031537-928513b29760", + name = "org_go4_netipx", + importpath = "go4.org/netipx", + sum = "h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s=", + version = "v0.0.0-20230125063823-8449b0a6169f", ) go_repository( name = "org_golang_google_api", @@ -2096,6 +2084,12 @@ def go_deps(): sum = "h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=", version = "v0.0.0-20220722155223-a9213eeb770e", ) + go_repository( + name = "org_golang_x_exp_typeparams", + importpath = "golang.org/x/exp/typeparams", + sum = "h1:qyrTQ++p1afMkO4DPEeLGq/3oTsdlvdH4vqZUBWzUKM=", + version = "v0.0.0-20220218215828-6cf2b201936e", + ) go_repository( name = "org_golang_x_image", importpath = "golang.org/x/image", diff --git a/licenses/data/org_go4_intern/LICENSE b/licenses/data/org_go4_intern/LICENSE deleted file mode 100644 index b0ab8921d..000000000 --- a/licenses/data/org_go4_intern/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2020, Brad Fitzpatrick -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/af_inet_netaddr/LICENSE b/licenses/data/org_go4_netipx/LICENSE similarity index 100% rename from licenses/data/af_inet_netaddr/LICENSE rename to licenses/data/org_go4_netipx/LICENSE diff --git a/licenses/data/org_go4_unsafe_assume_no_moving_gc/LICENSE b/licenses/data/org_go4_unsafe_assume_no_moving_gc/LICENSE deleted file mode 100644 index b0ab8921d..000000000 --- a/licenses/data/org_go4_unsafe_assume_no_moving_gc/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2020, Brad Fitzpatrick -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkg/experimental/hiddenpath/BUILD.bazel b/pkg/experimental/hiddenpath/BUILD.bazel index 5da8e413a..ee33cdb96 100644 --- a/pkg/experimental/hiddenpath/BUILD.bazel +++ b/pkg/experimental/hiddenpath/BUILD.bazel @@ -74,7 +74,6 @@ go_test( "//private/pathdb/query:go_default_library", "//private/topology:go_default_library", "//private/trust:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_golang_mock//gomock:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/pkg/experimental/hiddenpath/beaconwriter_test.go b/pkg/experimental/hiddenpath/beaconwriter_test.go index 89a6188cf..95c089107 100644 --- a/pkg/experimental/hiddenpath/beaconwriter_test.go +++ b/pkg/experimental/hiddenpath/beaconwriter_test.go @@ -22,6 +22,7 @@ import ( "crypto/rand" "hash" "net" + "net/netip" "sort" "testing" "time" @@ -29,7 +30,6 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "inet.af/netaddr" "github.com/scionproto/scion/control/beacon" "github.com/scionproto/scion/control/beaconing" @@ -82,7 +82,7 @@ func TestRemoteBeaconWriterWrite(t *testing.T) { assert.Equal(t, pathHopField.ConsEgress, segHopField.ConsEgress) nextHop := pathHopField.ConsIngress - ta := interfaceInfos(topo)[nextHop].InternalAddr.UDPAddr() + ta := net.UDPAddrFromAddrPort(interfaceInfos(topo)[nextHop].InternalAddr) assert.Equal(t, ta, a.NextHop) } } @@ -360,7 +360,7 @@ func interfaceInfos(topo topology.Topology) map[uint16]ifstate.InterfaceInfo { ID: uint16(info.ID), IA: info.IA, LinkType: info.LinkType, - InternalAddr: netaddr.MustParseIPPort(info.InternalAddr.String()), + InternalAddr: netip.MustParseAddrPort(info.InternalAddr.String()), RemoteID: uint16(info.RemoteIFID), MTU: uint16(info.MTU), } diff --git a/pkg/private/xtest/BUILD.bazel b/pkg/private/xtest/BUILD.bazel index aebaf656e..cb693100c 100644 --- a/pkg/private/xtest/BUILD.bazel +++ b/pkg/private/xtest/BUILD.bazel @@ -13,7 +13,6 @@ go_library( deps = [ "//pkg/addr:go_default_library", "//pkg/scrypto/cppki:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", "@org_golang_google_grpc//:go_default_library", diff --git a/pkg/private/xtest/helpers.go b/pkg/private/xtest/helpers.go index 406e1d910..70c893762 100644 --- a/pkg/private/xtest/helpers.go +++ b/pkg/private/xtest/helpers.go @@ -21,6 +21,7 @@ import ( "encoding/json" "flag" "net" + "net/netip" "os" "path/filepath" "regexp" @@ -29,7 +30,6 @@ import ( "time" "github.com/stretchr/testify/require" - "inet.af/netaddr" "github.com/scionproto/scion/pkg/addr" ) @@ -268,12 +268,12 @@ func MustParseCIDRs(t *testing.T, entries ...string) []*net.IPNet { } // MustParseIPPrefixes parses the CIDR entries and returns a list containing the -// parsed netaddr.IPPrefix objects. -func MustParseIPPrefixes(t *testing.T, prefixes ...string) []netaddr.IPPrefix { +// parsed netip.Prefix objects. +func MustParseIPPrefixes(t *testing.T, prefixes ...string) []netip.Prefix { t.Helper() - var result []netaddr.IPPrefix + var result []netip.Prefix for _, prefix := range prefixes { - p, err := netaddr.ParseIPPrefix(prefix) + p, err := netip.ParsePrefix(prefix) require.NoError(t, err) result = append(result, p) } diff --git a/pkg/snet/BUILD.bazel b/pkg/snet/BUILD.bazel index d2ab4a31b..66f0c6f67 100644 --- a/pkg/snet/BUILD.bazel +++ b/pkg/snet/BUILD.bazel @@ -33,7 +33,6 @@ go_library( "//pkg/slayers/path/epic:go_default_library", "//pkg/sock/reliable:go_default_library", "//private/topology/underlay:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_google_gopacket//:go_default_library", ], ) diff --git a/pkg/snet/udpaddr.go b/pkg/snet/udpaddr.go index b20768117..6d741fea7 100644 --- a/pkg/snet/udpaddr.go +++ b/pkg/snet/udpaddr.go @@ -22,8 +22,6 @@ import ( "strconv" "strings" - "inet.af/netaddr" - "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/serrors" ) @@ -191,8 +189,8 @@ func parseAddr(s string) (string, string, error) { } func ipOnly(s string) bool { - _, portErr := netaddr.ParseIPPort(s) - _, ipErr := netaddr.ParseIP(strings.Trim(s, "[]")) + _, portErr := netip.ParseAddrPort(s) + _, ipErr := netip.ParseAddr(strings.Trim(s, "[]")) return portErr != nil && ipErr == nil } diff --git a/private/app/flag/BUILD.bazel b/private/app/flag/BUILD.bazel index f64242045..2dddf09ad 100644 --- a/private/app/flag/BUILD.bazel +++ b/private/app/flag/BUILD.bazel @@ -16,7 +16,6 @@ go_library( "//pkg/private/util:go_default_library", "//pkg/sock/reliable:go_default_library", "//private/app/env:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_spf13_pflag//:go_default_library", ], ) @@ -34,7 +33,6 @@ go_test( "//pkg/private/xtest:go_default_library", "//pkg/sock/reliable:go_default_library", "//private/app/env:go_default_library", - "@af_inet_netaddr//:go_default_library", "@com_github_spf13_pflag//:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/private/app/flag/env.go b/private/app/flag/env.go index b223e0b70..964534f62 100644 --- a/private/app/flag/env.go +++ b/private/app/flag/env.go @@ -18,11 +18,11 @@ import ( "encoding/json" "errors" "io/fs" + "net/netip" "os" "sync" "github.com/spf13/pflag" - "inet.af/netaddr" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/daemon" @@ -62,10 +62,10 @@ func (v *iaVal) Set(val string) error { func (v *iaVal) Type() string { return "isd-as" } func (v *iaVal) String() string { return addr.IA(*v).String() } -type ipVal netaddr.IP +type ipVal netip.Addr func (v *ipVal) Set(val string) error { - ip, err := netaddr.ParseIP(val) + ip, err := netip.ParseAddr(val) if err != nil { return err } @@ -74,7 +74,7 @@ func (v *ipVal) Set(val string) error { } func (v *ipVal) Type() string { return "ip" } -func (v *ipVal) String() string { return netaddr.IP(*v).String() } +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, the dispatcher socket address and the local IP @@ -86,8 +86,8 @@ type SCIONEnvironment struct { iaFlag *pflag.Flag dispFlag *pflag.Flag dispEnv *string - local netaddr.IP - localEnv *netaddr.IP + local netip.Addr + localEnv *netip.Addr localFlag *pflag.Flag file env.SCION filepath string @@ -165,7 +165,7 @@ func (e *SCIONEnvironment) loadEnv() error { e.dispEnv = &d } if l, ok := os.LookupEnv("SCION_LOCAL_ADDR"); ok { - a, err := netaddr.ParseIP(l) + a, err := netip.ParseAddr(l) if err != nil { return serrors.WrapStr("parsing SCION_LOCAL_ADDR", err) } @@ -222,12 +222,12 @@ func (e *SCIONEnvironment) Dispatcher() string { return defaultDispatcher } -// Local returns the loca IP to listen on. The value is loaded from one of the +// Local returns the local IP to listen on. The value is loaded from one of the // following sources with the precedence as listed: // 1. Command line flag // 2. Environment variable // 3. Default value. -func (e *SCIONEnvironment) Local() netaddr.IP { +func (e *SCIONEnvironment) Local() netip.Addr { e.mtx.Lock() defer e.mtx.Unlock() @@ -237,5 +237,5 @@ func (e *SCIONEnvironment) Local() netaddr.IP { if e.localEnv != nil { return *e.localEnv } - return netaddr.IP{} + return netip.Addr{} } diff --git a/private/app/flag/env_test.go b/private/app/flag/env_test.go index 4aafe8609..cb5d9737c 100644 --- a/private/app/flag/env_test.go +++ b/private/app/flag/env_test.go @@ -16,13 +16,13 @@ package flag_test import ( "encoding/json" + "net/netip" "os" "testing" "github.com/spf13/pflag" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "inet.af/netaddr" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/daemon" @@ -79,7 +79,7 @@ func TestSCIONEnvironment(t *testing.T) { env func(t *testing.T) daemon string dispatcher string - local netaddr.IP + local netip.Addr }{ "no flag, no file, no env, defaults only": { flags: noFlags, @@ -87,7 +87,7 @@ func TestSCIONEnvironment(t *testing.T) { file: noFile, daemon: daemon.DefaultAPIAddress, dispatcher: reliable.DefaultDispPath, - local: netaddr.IP{}, + local: netip.Addr{}, }, "flag values set": { flags: setupFlags, @@ -95,7 +95,7 @@ func TestSCIONEnvironment(t *testing.T) { file: noFile, daemon: "scion:1234", dispatcher: "/test/dispatcher.socket", - local: netaddr.MustParseIP("10.0.0.42"), + local: netip.MustParseAddr("10.0.0.42"), }, "env values set": { flags: noFlags, @@ -103,7 +103,7 @@ func TestSCIONEnvironment(t *testing.T) { file: noFile, daemon: "scion_env:1234", dispatcher: "/test/dispatcher_env.socket", - local: netaddr.MustParseIP("10.0.42.0"), + local: netip.MustParseAddr("10.0.42.0"), }, "file values set": { flags: noFlags, @@ -111,7 +111,7 @@ func TestSCIONEnvironment(t *testing.T) { file: setupFile, daemon: "scion_file:1234", dispatcher: "/test/dispatcher_file.socket", - local: netaddr.IP{}, + local: netip.Addr{}, }, "all set, flag precedence": { flags: setupFlags, @@ -119,7 +119,7 @@ func TestSCIONEnvironment(t *testing.T) { file: setupFile, daemon: "scion:1234", dispatcher: "/test/dispatcher.socket", - local: netaddr.MustParseIP("10.0.0.42"), + local: netip.MustParseAddr("10.0.0.42"), }, "env set, file set, env precedence": { flags: noFlags, @@ -127,7 +127,7 @@ func TestSCIONEnvironment(t *testing.T) { file: setupFile, daemon: "scion_env:1234", dispatcher: "/test/dispatcher_env.socket", - local: netaddr.MustParseIP("10.0.42.0"), + local: netip.MustParseAddr("10.0.42.0"), }, } for name, tc := range testCases { diff --git a/scion-pki/certs/renew.go b/scion-pki/certs/renew.go index 7ae4a1e57..498b6d277 100644 --- a/scion-pki/certs/renew.go +++ b/scion-pki/certs/renew.go @@ -264,7 +264,7 @@ The template is expressed in JSON. A valid example:: } daemonAddr := envFlags.Daemon() dispatcher := envFlags.Dispatcher() - localIP := envFlags.Local().IPAddr().IP + localIP := net.IP(envFlags.Local().AsSlice()) log.Debug("Resolved SCION environment flags", "daemon", daemonAddr, "dispatcher", dispatcher, diff --git a/scion/cmd/scion/ping.go b/scion/cmd/scion/ping.go index 065f4fd28..df6bf02ac 100644 --- a/scion/cmd/scion/ping.go +++ b/scion/cmd/scion/ping.go @@ -132,7 +132,7 @@ On other errors, ping will exit with code 2. } daemonAddr := envFlags.Daemon() dispatcher := envFlags.Dispatcher() - localIP := envFlags.Local().IPAddr().IP + localIP := net.IP(envFlags.Local().AsSlice()) log.Debug("Resolved SCION environment flags", "daemon", daemonAddr, "dispatcher", dispatcher, diff --git a/scion/cmd/scion/showpaths.go b/scion/cmd/scion/showpaths.go index f531ed9e9..54e328299 100644 --- a/scion/cmd/scion/showpaths.go +++ b/scion/cmd/scion/showpaths.go @@ -18,6 +18,7 @@ import ( "context" "encoding/json" "fmt" + "net" "os" "time" @@ -99,7 +100,7 @@ On other errors, showpaths will exit with code 2. flags.cfg.Daemon = envFlags.Daemon() flags.cfg.Dispatcher = envFlags.Dispatcher() - flags.cfg.Local = envFlags.Local().IPAddr().IP + flags.cfg.Local = net.IP(envFlags.Local().AsSlice()) log.Debug("Resolved SCION environment flags", "daemon", flags.cfg.Daemon, "dispatcher", flags.cfg.Dispatcher, diff --git a/scion/cmd/scion/traceroute.go b/scion/cmd/scion/traceroute.go index 228bb3773..0bdf6a523 100644 --- a/scion/cmd/scion/traceroute.go +++ b/scion/cmd/scion/traceroute.go @@ -108,7 +108,7 @@ On other errors, traceroute will exit with code 2. } daemonAddr := envFlags.Daemon() dispatcher := envFlags.Dispatcher() - localIP := envFlags.Local().IPAddr().IP + localIP := net.IP(envFlags.Local().AsSlice()) log.Debug("Resolved SCION environment flags", "daemon", daemonAddr, "dispatcher", dispatcher, From efd0aa15d78e248a1c93d7b15f216c773931dbd9 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Mon, 15 May 2023 09:00:57 +0200 Subject: [PATCH 023/255] router: fix minimal SCMP checks in dataplane tests (#4343) There is a small number of of packet processing test cases that cover cases resulting in SCMPs. The packet processor signals SCMPs by returning an `scmpError`. Previously, the test cases just asserted that any error is returned from processing and so they would pass even if an internal error occurred. In this instance there was an internal error while serializing the SCMP message, as the internal IP of the dataplane, the source address of the SCMP message, was not initialized in the test setup. Add a dummy internal IP address to the test dataplane setup, and change the type of the dataplane's internal IP so that a missing initialization of the IP leads to a panic instead of a runtime error. Assert that an `scmpError` is returned for the relevant test cases, and check the SCMP type/code. The full SCMP message is still not checked. --- router/dataplane.go | 6 +++--- router/dataplane_test.go | 34 ++++++++++++++++++---------------- router/export_test.go | 3 +++ 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/router/dataplane.go b/router/dataplane.go index 6365b9784..341097968 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -99,7 +99,7 @@ type DataPlane struct { linkTypes map[uint16]topology.LinkType neighborIAs map[uint16]addr.IA internal BatchConn - internalIP net.IP + internalIP *net.IPAddr internalNextHops map[uint16]*net.UDPAddr svc *services macFactory func() hash.Hash @@ -203,7 +203,7 @@ func (d *DataPlane) AddInternalInterface(conn BatchConn, ip net.IP) error { return alreadySet } d.internal = conn - d.internalIP = ip + d.internalIP = &net.IPAddr{IP: ip} return nil } @@ -1624,7 +1624,7 @@ func (p *scionPacketProcessor) prepareSCMP( if err := scionL.SetDstAddr(srcA); err != nil { return nil, serrors.Wrap(cannotRoute, err, "details", "setting dest addr") } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: p.d.internalIP}); err != nil { + if err := scionL.SetSrcAddr(p.d.internalIP); err != nil { return nil, serrors.Wrap(cannotRoute, err, "details", "setting src addr") } scionL.NextHdr = slayers.L4SCMP diff --git a/router/dataplane_test.go b/router/dataplane_test.go index 34ddf66aa..d68d95336 100644 --- a/router/dataplane_test.go +++ b/router/dataplane_test.go @@ -837,14 +837,10 @@ func TestProcessPkt(t *testing.T) { dpath.Base.PathMeta.CurrHF = 2 dpath.HopFields[2].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[2]) ret := toMsg(t, spkt, dpath) - if afterProcessing { - ret.Addr = &net.IPAddr{IP: net.ParseIP("10.0.200.200").To4()} - ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil - } return ret }, srcInterface: 1, - assertFunc: assert.Error, + assertFunc: assertIsSCMPError(slayers.SCMPTypeDestinationUnreachable, 0), }, "svc invalid": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -864,14 +860,10 @@ func TestProcessPkt(t *testing.T) { dpath.Base.PathMeta.CurrHF = 2 dpath.HopFields[2].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[2]) ret := toMsg(t, spkt, dpath) - if afterProcessing { - ret.Addr = &net.IPAddr{IP: net.ParseIP("10.0.200.200").To4()} - ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil - } return ret }, srcInterface: 1, - assertFunc: assert.Error, + assertFunc: assertIsSCMPError(slayers.SCMPTypeDestinationUnreachable, 0), }, "onehop inbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -1090,17 +1082,16 @@ func TestProcessPkt(t *testing.T) { {ConsIngress: 31, ConsEgress: 404}, {ConsIngress: 1, ConsEgress: 0}, } - dpath.Base.PathMeta.CurrHF = 1 + dpath.Base.PathMeta.CurrHF = 2 dpath.HopFields[1].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[1]) ret := toMsg(t, spkt, dpath) - if afterProcessing { - ret.Addr = &net.IPAddr{IP: net.ParseIP("10.0.200.200").To4()} - ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil - } return ret }, srcInterface: 1, - assertFunc: assert.Error, + assertFunc: assertIsSCMPError( + slayers.SCMPTypeParameterProblem, + slayers.SCMPCodeInvalidDestinationAddress, + ), }, "epic inbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -1325,3 +1316,14 @@ func bfd() control.BFD { RequiredMinRxInterval: 25 * time.Millisecond, } } + +// assertIsSCMPError returns an ErrorAssertionFunc asserting that error is an +// scmpError with the specified type/code. +func assertIsSCMPError(typ slayers.SCMPType, code slayers.SCMPCode) assert.ErrorAssertionFunc { + return func(t assert.TestingT, err error, args ...interface{}) bool { + target := router.SCMPError{} + return assert.ErrorAs(t, err, &target, args) && + assert.Equal(t, typ, target.TypeCode.Type(), args) && + assert.Equal(t, code, target.TypeCode.Code(), args) + } +} diff --git a/router/export_test.go b/router/export_test.go index f09660947..3a9acc5c8 100644 --- a/router/export_test.go +++ b/router/export_test.go @@ -29,6 +29,8 @@ type ProcessResult struct { processResult } +type SCMPError = scmpError + func NewDP( external map[uint16]BatchConn, linkTypes map[uint16]topology.LinkType, @@ -47,6 +49,7 @@ func NewDP( internalNextHops: internalNextHops, svc: &services{m: svc}, internal: internal, + internalIP: &net.IPAddr{IP: net.ParseIP("198.51.100.1")}, } if err := dp.SetKey(key); err != nil { panic(err) From 086d9b73bed2d7e77923e78e626ac8336a2eda3d Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Tue, 16 May 2023 11:00:30 +0200 Subject: [PATCH 024/255] doc: reorganize and extend documentation (#4325) The documentation has been a somewhat unsorted bag of documents. It was mostly focused on contributors to this project, but some sections did target users of the software, without a clear distinction. This PR attempts to bring some more structure into this. There are now three separate sections: - Technology: Explanations and Specifications. Explain SCION on a conceptual level. Should introduce concepts that a user or dev needs to make sense of the manuals etc. Target audience: anyone (users, developers, outsiders) - Reference manuals: Target audience: users of this SCION implementation (operator of SCION infrastructure or hosts), users of any of the SCION APIs. - Developer section: Target audience: contributors to this SCION implementation In particular, the developer section now "hides" the design documents away a bit and the intended workflow for these documents is clarified. There is still a lot to do, in particular for overview and introductory material and the manuals. I've started to work on the manual for the control service, but I've decided to defer this for a separate PR so that we can finalize the organizational changes. Note that the content of some design documents, in particular the one on path policies is now relegated to the less findable design document section. The relevant information will be included in the manuals again. --- doc/BUILD.bazel | 1 - doc/beacon-metadata.rst | 2 +- doc/build/setup.rst | 253 ------------- doc/conf.py | 51 ++- doc/contribute/bazel-style.rst | 9 - doc/contribute/json-style.rst | 8 - doc/contribute/metrics_test | 1 - doc/contribute/python-style.rst | 8 - doc/contribute/toml-style.rst | 9 - doc/contribute/wrappers_test | 1 - doc/control-plane.rst | 20 ++ doc/cryptography/drkey.rst | 2 +- doc/cryptography/index.rst | 5 +- doc/css/custom.css | 11 + doc/data-plane.rst | 18 + doc/{ => dev}/contribute.rst | 79 ++--- doc/{build => dev}/dependencies.rst | 4 +- doc/{ => dev/design}/BeaconService.md | 5 +- doc/{ => dev/design}/ColibriService.md | 7 + doc/{ => dev/design}/EPIC.md | 12 +- doc/{ => dev/design}/PathPolicy.md | 21 +- doc/{ => dev/design}/PathService.md | 3 +- doc/dev/design/TEMPLATE.rst | 31 ++ doc/{ => dev/design}/endhost-bootstrap.rst | 7 +- .../fig/EPIC/path-type-filtering-small.png | Bin .../design}/fig/EPIC/path-type-filtering.png | Bin .../fig/beacon_srv/beaconing_overview.png | Bin .../design}/fig/beacon_srv/db_overview.png | Bin .../fig/beacon_srv/ifstate_overview.png | Bin doc/{ => dev/design}/fig/colibri_srv/COS.png | Bin doc/{ => dev/design}/fig/colibri_srv/DB.png | Bin .../rollover-4-slot-rollover.png | Bin .../rollover-invalid-lifetime.png | Bin .../rollover-key-choice.png | Bin .../rollover-origination-time.png | Bin .../rollover-slot-rollover-a.png | Bin .../rollover-slot-rollover-b.png | Bin .../rollover-two-key-choices.png | Bin doc/{ => dev/design}/fig/grpc/grpc.png | Bin .../fig/grpc/grpc_channels_mapping.png | Bin .../fig/grpc/grpc_on_http2_mapping.png | Bin doc/{ => dev/design}/fig/path_lookup.png | Bin doc/{ => dev/design}/fig/path_lookup.txt | 0 .../design}/forwarding-key-rollover.rst | 11 +- doc/{ => dev/design}/grpc.rst | 8 + doc/dev/design/index.rst | 73 ++++ doc/{ => dev/design}/uri.rst | 8 + .../change-proposal-process.excalidraw.png | Bin doc/{contribute => dev}/git.rst | 4 +- doc/{contribute => dev}/go-learn.rst | 4 +- doc/dev/run.rst | 192 ++++++++++ doc/dev/setup.rst | 122 +++++++ .../go-style.rst => dev/style/go.rst} | 8 +- doc/dev/style/index.rst | 19 + .../rst-style.rst => dev/style/rst.rst} | 61 +++- doc/{ => dev}/testing/buildkite.rst | 9 +- doc/{ => dev}/testing/crypto.rst | 0 ...kite-elastic-stack-overview.excalidraw.png | Bin doc/{ => dev}/testing/goldenfiles.rst | 0 doc/{ => dev}/testing/hiddenpaths.png | Bin doc/{ => dev}/testing/hiddenpaths.rst | 0 doc/{ => dev}/testing/hiddenpaths.xml | 0 doc/dev/testing/index.rst | 67 ++++ doc/{ => dev}/testing/mocks.rst | 4 +- doc/{build => dev}/wireshark.png | Bin doc/dev/wireshark.rst | 103 ++++++ doc/fig/overview-routing.excalidraw.png | Bin 0 -> 35469 bytes doc/glossary.rst | 74 ++++ doc/hidden-paths.rst | 7 +- doc/index.rst | 136 +++++-- doc/manuals/common.rst | 331 +++++++++++++++++- doc/manuals/control/metrics.rst | 10 +- doc/manuals/router.rst | 147 ++++++++ doc/manuals/router/http-api.rst | 6 +- doc/manuals/router/metrics.rst | 8 - doc/overview.rst | 111 ++++++ doc/protocols/assigned-protocol-numbers.rst | 2 +- doc/protocols/bfd.rst | 5 +- doc/protocols/index.rst | 16 - doc/protocols/scion-header.rst | 6 +- doc/{protocols => }/sig.rst | 31 +- doc/testing/index.rst | 14 - 82 files changed, 1658 insertions(+), 507 deletions(-) delete mode 100644 doc/build/setup.rst delete mode 100644 doc/contribute/bazel-style.rst delete mode 100644 doc/contribute/json-style.rst delete mode 120000 doc/contribute/metrics_test delete mode 100644 doc/contribute/python-style.rst delete mode 100644 doc/contribute/toml-style.rst delete mode 120000 doc/contribute/wrappers_test create mode 100644 doc/control-plane.rst create mode 100644 doc/css/custom.css create mode 100644 doc/data-plane.rst rename doc/{ => dev}/contribute.rst (79%) rename doc/{build => dev}/dependencies.rst (97%) rename doc/{ => dev/design}/BeaconService.md (99%) rename doc/{ => dev/design}/ColibriService.md (96%) rename doc/{ => dev/design}/EPIC.md (95%) rename doc/{ => dev/design}/PathPolicy.md (91%) rename doc/{ => dev/design}/PathService.md (99%) create mode 100644 doc/dev/design/TEMPLATE.rst rename doc/{ => dev/design}/endhost-bootstrap.rst (97%) rename doc/{ => dev/design}/fig/EPIC/path-type-filtering-small.png (100%) rename doc/{ => dev/design}/fig/EPIC/path-type-filtering.png (100%) rename doc/{ => dev/design}/fig/beacon_srv/beaconing_overview.png (100%) rename doc/{ => dev/design}/fig/beacon_srv/db_overview.png (100%) rename doc/{ => dev/design}/fig/beacon_srv/ifstate_overview.png (100%) rename doc/{ => dev/design}/fig/colibri_srv/COS.png (100%) rename doc/{ => dev/design}/fig/colibri_srv/DB.png (100%) rename doc/{cryptography => dev/design}/fig/forwarding-key-rollover/rollover-4-slot-rollover.png (100%) rename doc/{cryptography => dev/design}/fig/forwarding-key-rollover/rollover-invalid-lifetime.png (100%) rename doc/{cryptography => dev/design}/fig/forwarding-key-rollover/rollover-key-choice.png (100%) rename doc/{cryptography => dev/design}/fig/forwarding-key-rollover/rollover-origination-time.png (100%) rename doc/{cryptography => dev/design}/fig/forwarding-key-rollover/rollover-slot-rollover-a.png (100%) rename doc/{cryptography => dev/design}/fig/forwarding-key-rollover/rollover-slot-rollover-b.png (100%) rename doc/{cryptography => dev/design}/fig/forwarding-key-rollover/rollover-two-key-choices.png (100%) rename doc/{ => dev/design}/fig/grpc/grpc.png (100%) rename doc/{ => dev/design}/fig/grpc/grpc_channels_mapping.png (100%) rename doc/{ => dev/design}/fig/grpc/grpc_on_http2_mapping.png (100%) rename doc/{ => dev/design}/fig/path_lookup.png (100%) rename doc/{ => dev/design}/fig/path_lookup.txt (100%) rename doc/{cryptography => dev/design}/forwarding-key-rollover.rst (98%) rename doc/{ => dev/design}/grpc.rst (98%) create mode 100644 doc/dev/design/index.rst rename doc/{ => dev/design}/uri.rst (97%) rename doc/{ => dev}/fig/change-proposal-process.excalidraw.png (100%) rename doc/{contribute => dev}/git.rst (98%) rename doc/{contribute => dev}/go-learn.rst (77%) create mode 100644 doc/dev/run.rst create mode 100644 doc/dev/setup.rst rename doc/{contribute/go-style.rst => dev/style/go.rst} (97%) create mode 100644 doc/dev/style/index.rst rename doc/{contribute/rst-style.rst => dev/style/rst.rst} (77%) rename doc/{ => dev}/testing/buildkite.rst (92%) rename doc/{ => dev}/testing/crypto.rst (100%) rename doc/{ => dev}/testing/fig/buildkite-elastic-stack-overview.excalidraw.png (100%) rename doc/{ => dev}/testing/goldenfiles.rst (100%) rename doc/{ => dev}/testing/hiddenpaths.png (100%) rename doc/{ => dev}/testing/hiddenpaths.rst (100%) rename doc/{ => dev}/testing/hiddenpaths.xml (100%) create mode 100644 doc/dev/testing/index.rst rename doc/{ => dev}/testing/mocks.rst (94%) rename doc/{build => dev}/wireshark.png (100%) create mode 100644 doc/dev/wireshark.rst create mode 100644 doc/fig/overview-routing.excalidraw.png create mode 100644 doc/glossary.rst create mode 100644 doc/overview.rst delete mode 100644 doc/protocols/index.rst rename doc/{protocols => }/sig.rst (87%) delete mode 100644 doc/testing/index.rst diff --git a/doc/BUILD.bazel b/doc/BUILD.bazel index 76829dc39..e69de29bb 100644 --- a/doc/BUILD.bazel +++ b/doc/BUILD.bazel @@ -1 +0,0 @@ -exports_files(["PathPolicy.md"]) diff --git a/doc/beacon-metadata.rst b/doc/beacon-metadata.rst index e0840cc6c..deaa479ad 100644 --- a/doc/beacon-metadata.rst +++ b/doc/beacon-metadata.rst @@ -236,7 +236,7 @@ For now it distinguishes three different types of links: Use cases of such information include: - Mitigating security concerns. -- Allowing users to select paths that e.g. avoid the open internet. +- Allowing users to select paths that e.g. avoid the open Internet. Internal Hops ------------- diff --git a/doc/build/setup.rst b/doc/build/setup.rst deleted file mode 100644 index d35eebcfe..000000000 --- a/doc/build/setup.rst +++ /dev/null @@ -1,253 +0,0 @@ -.. _setting-up-the-development-environment: - -Setting up the development environment -====================================== - -Prerequisites -------------- - -#. Make sure that you are using a clean and recently updated **Ubuntu 18.04**. - Other Ubuntu versions (or systems) will usually be fine too, but some of the tooling may not work. - This environment assumes you're running as a non-root user with ``sudo`` access. -#. Install ``docker``. - Please follow the instructions for `docker-ce `_. - Then, add your user to the ``docker`` group: - ``sudo usermod -a -G docker ${LOGNAME}``, where ``${LOGNAME}`` is replaced with your user name. Log out - and log back in so that your membership of the ``docker`` group is seen by the shell session. - - Optionally install ``docker-compose``. This is needed if you want to run the - ``docker-compose`` based test topology setup instead of the default setup based on ``supervisord``. - Please follow the instructions for `docker-compose `_. - -Bazel & Co. ------------ - -#. Clone the SCION repository into the appropriate directory inside your workspace. In the commands below, - replace ``${WORKSPACE}`` with the directory in which you want to set up the project: - - .. code-block:: bash - - cd ${WORKSPACE} - git clone https://github.com/scionproto/scion - cd scion - -#. We use `Bazel `__ for both building and testing. To be - able to define the bazel version in the repository we use the `bazelisk - `__ wrapper around bazel. To set it - up simply use:: - - ./tools/install_bazel - - and make sure that ``~/bin`` is on your ``PATH``. - - You can also manually install ``bazelisk`` and create an alias so that - ``bazel`` will resolve to the ``bazelisk`` command. - -#. To install the required dependencies, run: - - .. code-block:: bash - - ./tools/install_deps - -#. Start the bazel-remote container. - - We use `bazel-remote `_ to cache - build artifacts from bazel. Bazel-remote can manage the disk space and does - not infinitely grow like the Bazel built-in disk-cache. To start bazel-remote run:: - - ./scion.sh bazel_remote - -#. Build SCION services and tools. - - .. code-block:: bash - - make - -#. Finally, check that tests run correctly: - - .. code-block:: bash - - make test - make test-integration - -#. (Optional) If you already have some code you wish to contribute upstream, you can also run the - linters locally with: - - .. code-block:: bash - - make lint - - -Alternative: go build ---------------------- - -Alternatively to building with bazel, the SCION services and tools can be built -with ``go build``. -Please be aware that **this is not the recommended setup for development**. -Not all checks and linters can be run in this setup. Without running all checks -locally, it is likely that there will be frustrating cycles with the CI system -rejecting your changes. - -#. Determine the go version used in the bazel setup; the ``WORKSPACE`` file - specifies this version in the ``go_register_toolchains`` clause. - - .. literalinclude:: ../../WORKSPACE - :start-at: go_register_toolchains( - :end-at: ) - :emphasize-lines: 3 - - Building with newer go versions *usually* works. - -#. Install go. Either follow `the official instructions `_ - or check the `Ubuntu specific installation options on the golang wiki `_. - -#. Build SCION services and tools. - - .. code-block:: bash - - go build -o bin .//cmd/... - - -Running SCION locally ---------------------- - -#. SCION networks are composed of many different applications. To simplify testing, we provide a - tool that generates test topologies. To generate the files required by the default topology (see - ``doc/fig/default_topo.png`` for a diagram of this topology), run: - - .. code-block:: bash - - ./scion.sh topology - - The above command creates the ``gen`` directory, which contains configuration files and cryptographic - material for multiple SCION ASes and ISDs. - - .. Attention:: The certificates created by this command expire after 3 days if the - infrastructure is not running for automatic renewal. - -#. To start the infrastructure we just generated, run: - - .. code-block:: bash - - ./scion.sh run - -#. To verify that your topology is running correctly, you can run an end to end reachability test using: - - .. code-block:: bash - - ./bin/end2end_integration - -#. This local infrastructure runs multiple SCION daemons, one in each AS. - We need to specify which instance is used when running end-host applications - that rely on the SCION daemon, e.g. to query paths. - - The ``scion.sh topology`` script writes a file ``gen/sciond_address.json``, - mapping AS numbers to SCION daemon instance addresses. Either consult this - file manually, or use the ``scion.sh sciond-addr`` command: - - .. code-block:: bash - - # show paths from 1-ff00:0:112 to 1-ff00:0:110 - ./bin/scion showpaths --sciond $(./scion.sh sciond-addr 112) 1-ff00:0:110 - - -#. To stop the infrastructure, run: - - .. code-block:: bash - - ./scion.sh stop - - -Wireshark ---------- - -To inspect SCION packets that are sent over the wire it can be helpful to use -Wireshark. We use version 3.x of Wireshark, which is not shipped by default on -Ubuntu 18.04. To install it use: - -.. code-block:: bash - - sudo add-apt-repository ppa:wireshark-dev/stable - sudo apt-get update - sudo apt-get install wireshark - -To use the SCION dissector you need to install it: - -.. code-block:: bash - - mkdir -p ~/.wireshark/plugins - cp tools/wireshark/scion.lua ~/.wireshark/plugins - -After that you can test it by running a topology and using a SCION filter for -example:: - - tshark -Y 'scion.dst_as == "ff00:0:110"' - - -Work remotely with Wireshark -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Sometimes it can be handy to use the remote feature of wireshark to tap into an -interface on a different machine. - - -#. Install wireshark on your local OS. - - - For Ubuntu install as described in the steps above. - - For MacOS and Windows just download & install from the `wireshark website - `_. - - -#. Install dissector plugin - - To install the dissector lua plugin copy it in the plugin folder of wireshark: - - - Ubuntu: same as in the previous step - - Windows: ``%APPDATA%\Wireshark\plugins`` - - MacOS: ``/Applications/Wireshark.app/Contents/PlugIns/wireshark`` - - .. note:: - The folder needs to be created if it doesn't exist. - (for more details visit `wireshark website: Plugin folders - `_) - -#. Prepare the remote machine - - Install tcpdump:: - - sudo apt-get install tcpdump - - The user used to SSH into the remote machine needs to have full access to tcpdump. - Hence create a new group and add this user to the group. SSH into the remote machine - and execute:: - - sudo groupadd pcap - sudo usermod -a -G pcap $USER - - set this group as the owner of tcpdump:: - - sudo chgrp pcap /usr/sbin/tcpdump - sudo chmod 750 /usr/sbin/tcpdump - - give tcpdump the necessary permissions:: - - sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump - - .. note:: - This will allow every user part of the pcap group to use the full - capabilities of tcpdump! - -#. Figure out the network interface on the remote host you want to tap into: - Get an IP address used by the SCION topology that's probably running with docker. - Search for the network-interface that's with the corresponding subnet. - -#. Start wireshark and click on the gear next to the interface named - "SSH remote capture: sshdump" - Fill in the IP address and Port of the remote host, as well as your preferred - authentication method in the Authentication tab. - At the Capture tab write the name of the interface you found in the previous - step. Find the a screenshot of an example below: - - .. image:: wireshark.png - -#. Now you are ready to click start and investigate some SCION traffic - diff --git a/doc/conf.py b/doc/conf.py index 702fc43d7..4a466f4c7 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,20 +1,9 @@ # Configuration file for the Sphinx documentation builder. # -# This file only contains a selection of the most common options. For a full -# list see the documentation: +# See documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - -import sphinx_rtd_theme # noqa +import subprocess # -- Project information ----------------------------------------------------- @@ -31,6 +20,7 @@ extensions = [ 'recommonmark', 'sphinx_rtd_theme', + 'sphinx.ext.extlinks', ] # Add any paths that contain templates here, relative to this directory. @@ -43,10 +33,34 @@ 'venv', 'requirements.in', 'requirements.txt', '_build', 'Thumbs.db', '.DS_Store', 'manuals/*/*', # manuals/.rst uses "include" directive to compose files from subdirectories + 'dev/design/TEMPLATE.rst', ] master_doc = 'index' +nitpicky = True + +option_emphasise_placeholders = True + +# -- extlinks definitions for links to github --- + +# Determine current git commit for permalinks to files on github. +# Note: somewhat obviously, these links will only work if the current rev has been pushed. +try: + file_ref_commit = subprocess.run( + ['git', 'rev-parse', "HEAD"], + capture_output=True, text=True, check=True + ).stdout.strip() +except subprocess.CalledProcessError: + file_ref_commit = "master" # only used on unexpected problem with executing git + +extlinks = { + # :issue:`123` is an issue link displayed as "#123" + 'issue': ('https://github.com/scionproto/scion/issues/%s', '#%s'), + # :file-ref:`foo/bar.go` is a link to a file in the repo, displayed as "foo/bar.go" + 'file-ref': ('https://github.com/scionproto/scion/blob/'+file_ref_commit+'/%s', '%s'), +} + # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for @@ -54,7 +68,18 @@ # html_theme = 'sphinx_rtd_theme' +html_theme_options = dict( + style_external_links=True, +) + +manpages_url = "https://manpages.debian.org/{path}" + + # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [''] + +html_css_files = [ + 'css/custom.css', +] diff --git a/doc/contribute/bazel-style.rst b/doc/contribute/bazel-style.rst deleted file mode 100644 index 59b343c1a..000000000 --- a/doc/contribute/bazel-style.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _bazel-style-guide: - -***************** -Bazel style guide -***************** - -Bazel code must follow the official rules as defined in `the Bazel project -`__. - diff --git a/doc/contribute/json-style.rst b/doc/contribute/json-style.rst deleted file mode 100644 index aca4179dd..000000000 --- a/doc/contribute/json-style.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _json-style-guide: - -**************** -JSON style guide -**************** - -Property names must be ASCII snake_case. - diff --git a/doc/contribute/metrics_test b/doc/contribute/metrics_test deleted file mode 120000 index f84b9efe9..000000000 --- a/doc/contribute/metrics_test +++ /dev/null @@ -1 +0,0 @@ -../../pkg/metrics/metrics_test.go \ No newline at end of file diff --git a/doc/contribute/python-style.rst b/doc/contribute/python-style.rst deleted file mode 100644 index 783b03203..000000000 --- a/doc/contribute/python-style.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _python-style-guide: - -****************** -Python style guide -****************** - -We follow the `Google Style Guide for Python `__. - diff --git a/doc/contribute/toml-style.rst b/doc/contribute/toml-style.rst deleted file mode 100644 index c8885a76f..000000000 --- a/doc/contribute/toml-style.rst +++ /dev/null @@ -1,9 +0,0 @@ - -.. _toml-style-guide: - -**************** -TOML style guide -**************** - -Keys must be ASCII snake_case. - diff --git a/doc/contribute/wrappers_test b/doc/contribute/wrappers_test deleted file mode 120000 index f98d72350..000000000 --- a/doc/contribute/wrappers_test +++ /dev/null @@ -1 +0,0 @@ -../../pkg/log/wrappers_test.go \ No newline at end of file diff --git a/doc/control-plane.rst b/doc/control-plane.rst new file mode 100644 index 000000000..1ab5645bb --- /dev/null +++ b/doc/control-plane.rst @@ -0,0 +1,20 @@ +************* +Control Plane +************* + +.. toctree:: + :hidden: + :maxdepth: 1 + + + hidden-paths + beacon-metadata + +The SCION control plane is responsible for discovering path segments and making them available to +endpoints. This includes path-segment exploration (also called "beaconing"), registration, lookup, +and finally the combination of path-segments to end-to-end paths. + +.. admonition:: TODO + + Control plane overview and detailed description of beaconing, registration, lookup, and + combination diff --git a/doc/cryptography/drkey.rst b/doc/cryptography/drkey.rst index 304f50b7a..a0e80d401 100644 --- a/doc/cryptography/drkey.rst +++ b/doc/cryptography/drkey.rst @@ -4,7 +4,7 @@ Dynamically Recreatable Key (DRKey) Infrastructure ************************************************** -This document presents the design for the Dynamically Recreatable Key (DRKey) +This document describes the Dynamically Recreatable Key (DRKey) infrastructure. Overview diff --git a/doc/cryptography/index.rst b/doc/cryptography/index.rst index 19d623118..4945e66f1 100644 --- a/doc/cryptography/index.rst +++ b/doc/cryptography/index.rst @@ -2,8 +2,6 @@ SCION Cryptography ================== -Open source cryptography documentation: - .. toctree:: :maxdepth: 2 @@ -15,6 +13,5 @@ Open source cryptography documentation: trc-signing-ceremony-phases-sensitive ca-operations interactions - standards drkey - forwarding-key-rollover + standards diff --git a/doc/css/custom.css b/doc/css/custom.css new file mode 100644 index 000000000..4eb538444 --- /dev/null +++ b/doc/css/custom.css @@ -0,0 +1,11 @@ +/* copied from github.com/readthedocs/readthedocs.org, MIT © 2010 Read the Docs, Inc. & contributors */ +.wy-menu.wy-menu-vertical a.reference.external::after { + /* \00a0 = no break space */ + content: "\00a0\f08e"; + font-family: FontAwesome; + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + -webkit-font-smoothing: antialiased; +} diff --git a/doc/data-plane.rst b/doc/data-plane.rst new file mode 100644 index 000000000..e351c5ae8 --- /dev/null +++ b/doc/data-plane.rst @@ -0,0 +1,18 @@ +********** +Data Plane +********** + +.. admonition:: TODO + + Data plane overview + +.. toctree:: + :maxdepth: 2 + + protocols/scion-header + protocols/extension-header + protocols/scmp + protocols/authenticator-option + protocols/bfd + protocols/assigned-protocol-numbers + diff --git a/doc/contribute.rst b/doc/dev/contribute.rst similarity index 79% rename from doc/contribute.rst rename to doc/dev/contribute.rst index 94862e791..7f101a614 100644 --- a/doc/contribute.rst +++ b/doc/dev/contribute.rst @@ -1,26 +1,23 @@ .. _contribution-guide: -*********************************** -Contributing to the SCION code base -*********************************** +****************** +Contribution Guide +****************** Welcome to the SCION contribution guide! If you are interested in contributing to the project, this page will help you out on your journey to your first SCION commit. .. _slack: -Before starting out, just one thing: if you have any questions, you can always -find us on our `Slack workspace `__ or on our -`Github project page `__. Do not hesitate to -ask us anything, or feel free to just drop by and say "Hi". -Please use this invite link to `join scionproto Slack workspace `__. -.. note:: Note for Anapayans +.. Hint:: + If you have any questions, you can always find us + on our `Slack workspace `__ + or on our `Github project page `__. + Do not hesitate to ask us anything, or feel free to just drop by and say "Hi". + + Please use this invite link to `join scionproto Slack workspace `__. - This section contains general rules about how to contribute to the - open-source SCION project. If you are an Anapaya employee, some additional - rules may apply. Please see the internal Contribution Guide for more - information. What skills do you need to contribute? ====================================== @@ -30,31 +27,26 @@ with some of them, we have compiled a list containing some great resources to ge +----------------+----------------------------+------------------------------------------+ | Language | Contribution area | Tutorials | -+----------------+----------------------------+------------------------------------------+ -| Go | SCION Control-plane | :ref:`resources-for-learning-go` | -| | SCION Data-plane | | ++================+============================+==========================================+ +| Go | SCION Control-plane, | :doc:`go-learn` | +| | SCION Data-plane, | | | | SCION Tools | | +----------------+----------------------------+------------------------------------------+ -| Python | Acceptance testing | Coming soon | -| | Helper scripts | | +| Python, | Acceptance testing, | Coming soon | +| Bash | Helper scripts | | +----------------+----------------------------+------------------------------------------+ | Starlark | Bazel build/test system | Coming soon | +----------------+----------------------------+------------------------------------------+ -Contributing to the Python and Starlark code bases is a bit trickier, so if you're just now -starting out, we recommend going for Go first. - -You might also see some Bash and Makefile code in the code base. While this code changes from -time to time, we strongly discourage contributions to these areas. Code in these languages also -has a high chance of getting deleted completely in a refactoring pass. - For version control, we use Git and GitHub. For more information about using Git (including -links to resources to get you started if you've never used before), please visit :ref:`how-to-use-git-and-github`. +links to resources to get you started if you've never used before), please visit :doc:`git`. No matter what language you want to contribute to, one of the first steps to take is to set up a development environment. See :ref:`setting-up-the-development-environment` for the needed steps. If you encounter issues, please visit our :ref:`Slack ` and ask for help. +.. _finding-an-issue-to-contribute-to: + Finding an issue to contribute to ================================= @@ -77,7 +69,7 @@ you and guide you for the rest of the process. If you have any questions, please remember to shoot us a question on our :ref:`Slack `. Finally, make sure that the code you write adheres to the SCION project -:ref:`language-style-guides`. +:doc:`style/index`. .. _governance: @@ -88,9 +80,6 @@ The `Technical Committee (TC) Implementation `_ of the SCION Association are the custodians of the open-source SCION implementation projects. -.. rubric:: People - -The current members of the TC Implementation are: .. |span-github| raw:: html @@ -100,12 +89,17 @@ The current members of the TC Implementation are: +.. rubric:: People + +The current members of the TC Implementation are: + * Dominik Roos (|span-github| `@oncilla `_, |span-slack| @roosd) * François Wirz (|span-github| `@FR4NK-W `_, |span-slack| @frank) * Lukas Vogel (|span-github| `@lukedirtwalker `_, |span-slack| @luke) * Marc Frei (|span-github| `@marcfrei `_, |span-slack| @marcfrei) * Matthias Frei (|span-github| `@matzf `_, |span-slack| @matzf) + .. rubric:: Responsibilities and Tasks The TC Implementation has the following main responsibilities, as defined in its @@ -175,8 +169,9 @@ Formal Process community. :Design: If the proposal has been accepted, the authors submit a design document and - submit it to the repository (`doc/ `__) + submit it to the repository (:file-ref:`doc/dev/design`) in the form of a pull request. + See :doc:`design/index` for details. :Final review: The design document will be reviewed by the assigned technical team. Since all major points should already be agreed upon in the proposal review, this @@ -202,20 +197,16 @@ Learning resources .. toctree:: :maxdepth: 1 - contribute/go-learn.rst - contribute/git.rst + go-learn + git -.. _language-style-guides: +.. seealso:: -Language style guides -===================== + :doc:`setup` + Get started by :doc:`cloning the repository and installing the build tools `. -.. toctree:: - :maxdepth: 1 + :doc:`run` + :doc:`Run a SCION network ` on your development machine - contribute/bazel-style - contribute/go-style - contribute/json-style - contribute/python-style - contribute/rst-style - contribute/toml-style + :doc:`wireshark` + Install :doc:`wireshark` and the SCION packet dissector plugin to inspect packets on the wire. diff --git a/doc/build/dependencies.rst b/doc/dev/dependencies.rst similarity index 97% rename from doc/build/dependencies.rst rename to doc/dev/dependencies.rst index b29c01c00..bbeb02377 100644 --- a/doc/build/dependencies.rst +++ b/doc/dev/dependencies.rst @@ -1,7 +1,7 @@ .. _external-dependencies: -Managing external dependencies -============================== +Dependencies +============ Go -- diff --git a/doc/BeaconService.md b/doc/dev/design/BeaconService.md similarity index 99% rename from doc/BeaconService.md rename to doc/dev/design/BeaconService.md index 2c985e961..ac9e51444 100644 --- a/doc/BeaconService.md +++ b/doc/dev/design/BeaconService.md @@ -1,6 +1,7 @@ -# Beacon Service Design +# Beacon Service -​ +* Author: Lukas Vogel +* Status: **outdated** --- ⚠️ **NOTE** ⚠️
diff --git a/doc/ColibriService.md b/doc/dev/design/ColibriService.md similarity index 96% rename from doc/ColibriService.md rename to doc/dev/design/ColibriService.md index 0d3672afc..0401f592b 100644 --- a/doc/ColibriService.md +++ b/doc/dev/design/ColibriService.md @@ -1,5 +1,12 @@ # COLIBRI Service Design +* Author: Juan A. García Pardo +* Last updated: 2020-07-08 +* Status: **experimental**, prototype being developed in [netsec-ethz/scion:scionlab](https://github.com/netsec-ethz/scion/tree/scionlab) +* Discussion at: [#3653](https://github.com/scionproto/scion/issues/3653), [#3794](https://github.com/scionproto/scion/issues/3794) + +## Abstract + This document specifies the design of the COLIBRI service. It aims for correctness not completeness, and some parts of the design are deliberately not yet specified. diff --git a/doc/EPIC.md b/doc/dev/design/EPIC.md similarity index 95% rename from doc/EPIC.md rename to doc/dev/design/EPIC.md index 43da7e5f7..e879f701b 100644 --- a/doc/EPIC.md +++ b/doc/dev/design/EPIC.md @@ -1,4 +1,12 @@ -# EPIC Design +# EPIC for Hidden Paths + +- Author: Marc Wyss, Markus Legner +- Last updated: 2020-10-14 +- Status: **implemented** +- Discussion at: [#3884](https://github.com/scionproto/scion/issues/3653) +- Implemented in: [#3951](https://github.com/scionproto/scion/issues/3951), + [#3954](https://github.com/scionproto/scion/issues/3954), + [#4079](https://github.com/scionproto/scion/issues/4079) This file introduces EPIC and documents the design rationales and best practices for EPIC-HP. @@ -222,7 +230,7 @@ Proceedings of the USENIX Security Symposium [2] Design Document for the Hidden Path Infrastructure -[[Link]](hidden-paths) +[[Link]](/hidden-paths) [3] T. Lee, C. Pappas, A. Perrig, V. Gligor, and Y. Hu. (2017)
diff --git a/doc/PathPolicy.md b/doc/dev/design/PathPolicy.md similarity index 91% rename from doc/PathPolicy.md rename to doc/dev/design/PathPolicy.md index 16c25bdbf..0e108637a 100644 --- a/doc/PathPolicy.md +++ b/doc/dev/design/PathPolicy.md @@ -1,7 +1,19 @@ # Path Policy Language Design -The path policy language will be used by the path server, SCIOND and the beacon server for different -but overlapping purposes. +- Authors: Lukas Bischofberger, Lukas Vogel, Martin Sustrik +- Last updated: 2019-08-30 +- Status: partially **implemented** / partially outdated +- Discussion at: [#1909](https://github.com/scionproto/scion/pull/1909), + [#1976](https://github.com/scionproto/scion/pull/1976), + [#2324](https://github.com/scionproto/scion/pull/2324), + [#2346](https://github.com/scionproto/scion/pull/2346), + [#2349](https://github.com/scionproto/scion/pull/2349), + [#2839](https://github.com/scionproto/scion/pull/2839) + +The path policy language was originally intended be used by the path server, +SCIOND and the beacon server for different but overlapping purposes. +Now it is only used on the level of SCION applications, specifically, in the +gateway. ## Hop Predicate (HP) @@ -203,6 +215,11 @@ third option which denies only hops in AS _1-ff00:0:133_, is used. ## Path policies in path lookup +⚠️ **NOTE** ⚠️
+Outdated contents! This section is kept for historical purpose. + +--- + ### Requirements 1. The path lookup path policy languages has to be at least as expressive as what we offer to diff --git a/doc/PathService.md b/doc/dev/design/PathService.md similarity index 99% rename from doc/PathService.md rename to doc/dev/design/PathService.md index 13452ba46..ab54dd731 100644 --- a/doc/PathService.md +++ b/doc/dev/design/PathService.md @@ -1,6 +1,7 @@ # Path Service -​ +* Author: Lukas Vogel, Sergiu Costea, Matthias Frei +* Status: **outdated** --- ⚠️ **NOTE** ⚠️
diff --git a/doc/dev/design/TEMPLATE.rst b/doc/dev/design/TEMPLATE.rst new file mode 100644 index 000000000..d5771cfd1 --- /dev/null +++ b/doc/dev/design/TEMPLATE.rst @@ -0,0 +1,31 @@ +******* +[Title] +******* + +- Author(s): [Author Name(s)] +- Last updated: [Date (Year-Month-Day)] +- Discussion at: :issue:`NNNN` + +Abstract +======== +[An introduction of the necessary background and the problem being solved by the proposed change.] + +Background +========== +[Introduction of the topic, description of the problem being solved.] + +Proposal +======== +[A precise statement of the proposed change.] + +Rationale +========= +[A discussion of alternate approaches and the trade-offs, advantages, and disadvantages of the specified approach.] + +Compatibility +============= +[A discussion of breaking changes and how this change can be deployed.] + +Implementation +============== +[A description of the steps in the implementation, which components need to be changed and in which order.] diff --git a/doc/endhost-bootstrap.rst b/doc/dev/design/endhost-bootstrap.rst similarity index 97% rename from doc/endhost-bootstrap.rst rename to doc/dev/design/endhost-bootstrap.rst index 5e01163f8..499d3cc2d 100644 --- a/doc/endhost-bootstrap.rst +++ b/doc/dev/design/endhost-bootstrap.rst @@ -2,11 +2,10 @@ Automated end host bootstrapping ******************************** -This file documents the design of the end host bootstrapping. - - Author(s): Andrea Tulimiero, François Wirz - Last updated: 2021-03-09 -- Status: draft +- Status: **implemented** externally in `netsec-ethz/bootstrapper `_ +- Discussion at: `#3943 `_ Overview ======== @@ -14,7 +13,7 @@ Overview Low entry barriers are crucial to push people to experiment with new technologies. The goal of automated end host bootstrapping is to let anyone join the -SCION internet effortlessly. +SCION Internet effortlessly. From within an AS, all an end user needs to do is to install a package. In particular, the package contains a bootstrapper daemon that retrieves diff --git a/doc/fig/EPIC/path-type-filtering-small.png b/doc/dev/design/fig/EPIC/path-type-filtering-small.png similarity index 100% rename from doc/fig/EPIC/path-type-filtering-small.png rename to doc/dev/design/fig/EPIC/path-type-filtering-small.png diff --git a/doc/fig/EPIC/path-type-filtering.png b/doc/dev/design/fig/EPIC/path-type-filtering.png similarity index 100% rename from doc/fig/EPIC/path-type-filtering.png rename to doc/dev/design/fig/EPIC/path-type-filtering.png diff --git a/doc/fig/beacon_srv/beaconing_overview.png b/doc/dev/design/fig/beacon_srv/beaconing_overview.png similarity index 100% rename from doc/fig/beacon_srv/beaconing_overview.png rename to doc/dev/design/fig/beacon_srv/beaconing_overview.png diff --git a/doc/fig/beacon_srv/db_overview.png b/doc/dev/design/fig/beacon_srv/db_overview.png similarity index 100% rename from doc/fig/beacon_srv/db_overview.png rename to doc/dev/design/fig/beacon_srv/db_overview.png diff --git a/doc/fig/beacon_srv/ifstate_overview.png b/doc/dev/design/fig/beacon_srv/ifstate_overview.png similarity index 100% rename from doc/fig/beacon_srv/ifstate_overview.png rename to doc/dev/design/fig/beacon_srv/ifstate_overview.png diff --git a/doc/fig/colibri_srv/COS.png b/doc/dev/design/fig/colibri_srv/COS.png similarity index 100% rename from doc/fig/colibri_srv/COS.png rename to doc/dev/design/fig/colibri_srv/COS.png diff --git a/doc/fig/colibri_srv/DB.png b/doc/dev/design/fig/colibri_srv/DB.png similarity index 100% rename from doc/fig/colibri_srv/DB.png rename to doc/dev/design/fig/colibri_srv/DB.png diff --git a/doc/cryptography/fig/forwarding-key-rollover/rollover-4-slot-rollover.png b/doc/dev/design/fig/forwarding-key-rollover/rollover-4-slot-rollover.png similarity index 100% rename from doc/cryptography/fig/forwarding-key-rollover/rollover-4-slot-rollover.png rename to doc/dev/design/fig/forwarding-key-rollover/rollover-4-slot-rollover.png diff --git a/doc/cryptography/fig/forwarding-key-rollover/rollover-invalid-lifetime.png b/doc/dev/design/fig/forwarding-key-rollover/rollover-invalid-lifetime.png similarity index 100% rename from doc/cryptography/fig/forwarding-key-rollover/rollover-invalid-lifetime.png rename to doc/dev/design/fig/forwarding-key-rollover/rollover-invalid-lifetime.png diff --git a/doc/cryptography/fig/forwarding-key-rollover/rollover-key-choice.png b/doc/dev/design/fig/forwarding-key-rollover/rollover-key-choice.png similarity index 100% rename from doc/cryptography/fig/forwarding-key-rollover/rollover-key-choice.png rename to doc/dev/design/fig/forwarding-key-rollover/rollover-key-choice.png diff --git a/doc/cryptography/fig/forwarding-key-rollover/rollover-origination-time.png b/doc/dev/design/fig/forwarding-key-rollover/rollover-origination-time.png similarity index 100% rename from doc/cryptography/fig/forwarding-key-rollover/rollover-origination-time.png rename to doc/dev/design/fig/forwarding-key-rollover/rollover-origination-time.png diff --git a/doc/cryptography/fig/forwarding-key-rollover/rollover-slot-rollover-a.png b/doc/dev/design/fig/forwarding-key-rollover/rollover-slot-rollover-a.png similarity index 100% rename from doc/cryptography/fig/forwarding-key-rollover/rollover-slot-rollover-a.png rename to doc/dev/design/fig/forwarding-key-rollover/rollover-slot-rollover-a.png diff --git a/doc/cryptography/fig/forwarding-key-rollover/rollover-slot-rollover-b.png b/doc/dev/design/fig/forwarding-key-rollover/rollover-slot-rollover-b.png similarity index 100% rename from doc/cryptography/fig/forwarding-key-rollover/rollover-slot-rollover-b.png rename to doc/dev/design/fig/forwarding-key-rollover/rollover-slot-rollover-b.png diff --git a/doc/cryptography/fig/forwarding-key-rollover/rollover-two-key-choices.png b/doc/dev/design/fig/forwarding-key-rollover/rollover-two-key-choices.png similarity index 100% rename from doc/cryptography/fig/forwarding-key-rollover/rollover-two-key-choices.png rename to doc/dev/design/fig/forwarding-key-rollover/rollover-two-key-choices.png diff --git a/doc/fig/grpc/grpc.png b/doc/dev/design/fig/grpc/grpc.png similarity index 100% rename from doc/fig/grpc/grpc.png rename to doc/dev/design/fig/grpc/grpc.png diff --git a/doc/fig/grpc/grpc_channels_mapping.png b/doc/dev/design/fig/grpc/grpc_channels_mapping.png similarity index 100% rename from doc/fig/grpc/grpc_channels_mapping.png rename to doc/dev/design/fig/grpc/grpc_channels_mapping.png diff --git a/doc/fig/grpc/grpc_on_http2_mapping.png b/doc/dev/design/fig/grpc/grpc_on_http2_mapping.png similarity index 100% rename from doc/fig/grpc/grpc_on_http2_mapping.png rename to doc/dev/design/fig/grpc/grpc_on_http2_mapping.png diff --git a/doc/fig/path_lookup.png b/doc/dev/design/fig/path_lookup.png similarity index 100% rename from doc/fig/path_lookup.png rename to doc/dev/design/fig/path_lookup.png diff --git a/doc/fig/path_lookup.txt b/doc/dev/design/fig/path_lookup.txt similarity index 100% rename from doc/fig/path_lookup.txt rename to doc/dev/design/fig/path_lookup.txt diff --git a/doc/cryptography/forwarding-key-rollover.rst b/doc/dev/design/forwarding-key-rollover.rst similarity index 98% rename from doc/cryptography/forwarding-key-rollover.rst rename to doc/dev/design/forwarding-key-rollover.rst index 5a77f3f15..426bb1692 100644 --- a/doc/cryptography/forwarding-key-rollover.rst +++ b/doc/dev/design/forwarding-key-rollover.rst @@ -1,6 +1,11 @@ -****************************** -Forwarding key rollover design -****************************** +*********************** +Forwarding key rollover +*********************** + +- Author: Sergiu Costea +- Last updated: 2020-09-23 +- Status: **proposal** / **outdated** +- Discussion at: - This document describes an implementation for key rollover in a SCION AS. diff --git a/doc/grpc.rst b/doc/dev/design/grpc.rst similarity index 98% rename from doc/grpc.rst rename to doc/dev/design/grpc.rst index 6e74aced2..b01b388e7 100644 --- a/doc/grpc.rst +++ b/doc/dev/design/grpc.rst @@ -2,6 +2,14 @@ Teaching gRPC some path-awareness ********************************* +- Author: Dominik Roos +- Last updated: 2020-09-02 +- Status: **proposal** +- Discussion at: - + +Abstract +======== + The SCION control plane uses gRPC to have a reliable RPC mechanism. gRPC is very flexible, and employs powerful concepts that we can utilize to make our RPC stack path aware. diff --git a/doc/dev/design/index.rst b/doc/dev/design/index.rst new file mode 100644 index 000000000..c27ebde16 --- /dev/null +++ b/doc/dev/design/index.rst @@ -0,0 +1,73 @@ +**************** +Design Documents +**************** + +Design documents serve as an agreed upon plan for the implementation of +substantial changes and as a record of the design choices made. +See section :ref:`change-proposal-process` for the overview on the overall +contribution process. + +- **Creation**: + Design documents are created from the template :file-ref:`doc/dev/design/TEMPLATE.rst`. + + Once discussion on a change proposal converges and a design document is + approved, it is inserted to section :ref:`design-docs-active`. +- **Implementation**: + Together with the implementation of the change, user manuals and any other + documentation are updated. + + The design document is only updated if amendments to the described design are + found to be necessary during this phase. +- **Completion and Freeze**: + Once all parts of the implementation are completed, the design document is + marked as complete and the document moves to the section :ref:`design-docs-completed`. + + After this point, the design document is frozen as historical record and no + longer updated. Later substantial changes undergo the entire process again, + creating new design documents where appropriate. +- **Replacement**: + If the implementation has changed so much that a design document is no longer + a useful reference for the current system, it moves to section :ref:`design-docs-outdated`. + + +.. _design-docs-active: + +Active +====== +.. toctree:: + :maxdepth: 1 + + uri + grpc + ColibriService + +.. _design-docs-completed: + +Completed +========= +.. toctree:: + :maxdepth: 1 + + EPIC + PathPolicy + endhost-bootstrap + +.. _design-docs-outdated: + +Outdated +======== +.. toctree:: + :maxdepth: 1 + + BeaconService + PathService + forwarding-key-rollover + + +.. seealso:: + + :ref:`change-proposal-process` + Documentation of the overall :ref:`change-proposal-process`. + + :ref:`governance` + The :ref:`governance model ` describes who ultimately approves or rejects change proposals and design documents. diff --git a/doc/uri.rst b/doc/dev/design/uri.rst similarity index 97% rename from doc/uri.rst rename to doc/dev/design/uri.rst index 5ba37c8ef..5f4fe596e 100644 --- a/doc/uri.rst +++ b/doc/dev/design/uri.rst @@ -2,6 +2,14 @@ SCION Address URI encoding ************************** +- Author: Dominik Roos +- Last updated: 2020-09-02 +- Status: **proposal** +- Discussion at: - + +Abstract +======== + Certain libraries and applications rely on addresses encoded in an URI format. This document defines a URI syntax for encoding SCION addresses. diff --git a/doc/fig/change-proposal-process.excalidraw.png b/doc/dev/fig/change-proposal-process.excalidraw.png similarity index 100% rename from doc/fig/change-proposal-process.excalidraw.png rename to doc/dev/fig/change-proposal-process.excalidraw.png diff --git a/doc/contribute/git.rst b/doc/dev/git.rst similarity index 98% rename from doc/contribute/git.rst rename to doc/dev/git.rst index 212d16f76..b0897ffec 100644 --- a/doc/contribute/git.rst +++ b/doc/dev/git.rst @@ -1,5 +1,3 @@ -.. _how-to-use-git-and-github: - ************************* How to Use Git and GitHub ************************* @@ -96,7 +94,7 @@ Run the tests using: .. code-block:: bash - bazel test --config=unit_all + make test The above runs only the unit tests. As soon as you open your PR, some additional tests will run automatically. diff --git a/doc/contribute/go-learn.rst b/doc/dev/go-learn.rst similarity index 77% rename from doc/contribute/go-learn.rst rename to doc/dev/go-learn.rst index 4285b4b60..e3a920333 100644 --- a/doc/contribute/go-learn.rst +++ b/doc/dev/go-learn.rst @@ -1,5 +1,3 @@ -.. _resources-for-learning-go: - ************************* Resources for learning Go ************************* @@ -13,4 +11,4 @@ Here are some resources to help you on your journey to learn Go: - https://github.com/golang/go/wiki/LearnConcurrency - https://dave.cheney.net/2019/05/07/prefer-table-driven-tests -Also, please also check the SCION :ref:`go-style-guide` if haven't done so already. +Also, please also check the SCION :doc:`style/go` if haven't done so already. diff --git a/doc/dev/run.rst b/doc/dev/run.rst new file mode 100644 index 000000000..77563c6fc --- /dev/null +++ b/doc/dev/run.rst @@ -0,0 +1,192 @@ +********************* +Running SCION Locally +********************* + +SCION is an Internet architecture and SCION networks are composed of +many hosts running the SCION control-plane services, routers, and SCION-enabled +applications. +To simplify development, testing, and tinkering, we provide a tool that generates test +topologies and runs an entire SCION "Internet" on a single machine. Packets are +only sent between different processes on the same host, not over the network. + +Running SCION in this developement setup, is also called running a **local topology**. + +The scripts support two different process orchestrators as "backends": + +- `supervisor `_. This is the default and a bit more light-weight. Packets are sent over the loopback interface. +- `docker-compose `_. Runs individual processes in separate containers connected with docker network bridges. Only this mode supports running a "SCION-IP gateway". + + +.. TODO + - Describe configuration directory (referencing manuals) + - How to use + +Quickstart +========== + +.. admonition:: Prerequisites + + * :doc:`setup` + + * Build, using ``make`` + +#. Generate the control-plane PKI keys and certificates, configuration files, and process + orchestrator (supervisor or docker-compose) configuration. + + .. code-block:: bash + + ./scion.sh topology -c topology/tiny.topo + + + .. Attention:: The certificates created by this command expire after 3 days if the + infrastructure is not running for automatic renewal. + +#. To start the infrastructure we just generated, run: + + .. code-block:: bash + + ./scion.sh run + +#. To verify that your topology is running correctly, you can run an end to end reachability test using: + + .. code-block:: bash + + bin/end2end_integration + +#. This local infrastructure runs multiple SCION daemons, one in each AS. + We need to specify which instance is used when running applications + that rely on the SCION daemon, e.g. to query paths. + + .. code-block:: bash + + # show paths from 1-ff00:0:112 to 1-ff00:0:110 + bin/scion showpaths --sciond $(./scion.sh sciond-addr 112) 1-ff00:0:110 + + +#. To stop the infrastructure, run: + + .. code-block:: bash + + ./scion.sh stop + +Local Topology Environment +========================== + +The :option:`scion.sh topology` command generates configuration in the ``gen/`` directory in the +repository. + +There is a subdirectory for each AS (e.g. ``gen/ASff00_0_110`` for AS ``ff00:0:110``), containing +the configuration for the services and routers of that AS. +Specifically, these contain the :ref:`.toml ` configuration files for the individual +components and a shared :ref:`topology.json ` configuration. + +Various helper files are also generated for the benefit of scripts and tooling of the test infrastructure, +for example, ``gen/sciond_addresses.json`` is a simple mapping from AS number to the address of the +corresponding :doc:`scion daemon ` instance. + +supervisor +---------- +The ``gen/supervisord.conf`` configuration defines the programs that make up the local topology. + +All the SCION traffic goes via the loopback interface, the separation of the internal +networks of the simulated ASes is not enforced in any way. + +There is a single :doc:`/manuals/dispatcher` instance, receiving and sending the SCION packets for +the :doc:`/manuals/control` instances and SCION applications/tools in all simulated ASes. + +There is one :doc:`/manuals/daemon` instance running for each simulated AS. +Commands accessing the SCION network can be run directly from the host. The information about the +local AS in which the command is running, is determined by the SCION daemon instance that the +command connects to. +For example:: + + # show paths from 1-ff00:0:112 to 1-ff00:0:110 + bin/scion showpaths --sciond $(./scion.sh sciond-addr 112) 1-ff00:0:110 + + # reveal the full SCION address of a simulated host in in 1-ff00:0:111 + bin/scion address --sciond $(./scion.sh sciond-addr 111) + + # and now ping this host from inside AS 1-ff00:0:110, with interactive path prompt + bin/scion ping --sciond $(./scion.sh sciond-addr 110) 1-ff00:0:111,127.0.0.1 --interactive + +docker +------ +The main docker-compose file is ``gen/scion-dc.yml``. + +Each SCION service or router runs in a separate container, and the network access of the individual +containers is configured to mimick real-world connectivity. + +There are "tester" containers configured in each AS to mimick end hosts in a SCION AS. +These tester containers can be used to run commands accessing the SCION network. +As a shorthand for the somewhat unwieldy ``docker-compose`` invocation, the :file-ref:`tools/dc` +script can be used. For example:: + + # show paths from 1-ff00:0:112 to 1-ff00:0:110 + tools/dc exec_tester 1-ff00_0_112 bin/scion showpaths 1-ff00:0:110 + + # reveal the full SCION address of the tester container in 1-ff00:0:111 + tools/dc exec_tester 1-ff00_0_111 bin/scion address + + # and now ping this host from inside AS 1-ff00:0:110, with interactive path prompt + tools/dc exec_tester 1-ff00_0_110 bin/scion ping 1-ff00:0:111,172.20.0.29 + +Note that the ``--sciond`` flag does not need to be provided in this setup, as it's preconfigured +in the tester containers via the environment variable ``SCION_DAEMON``. + +scion.sh +======== + +:program:`scion.sh` is the developer script to setup and run a local topology. + +.. Note:: + The SCION tools and services need to be built **before** running these commands, using + ``make`` or ``make docker-images`` (when using the docker-compose configuration). + +The basic usage is ``./scion.sh ``. The main subcommands are: + +.. program:: scion.sh + +.. option:: topology + + Generate the control-plane PKI keys and certificates, configuration files, + and process orchestrator (supervisor or docker-compose) configuration + for a given network topopology defined in a + :file-ref:`*.topo configuration file `. + + .. program:: scion.sh topology + + .. option:: -c , --topo-config + + Path to the :file-ref:`*.topo configuration file `. + + .. option:: -d, --docker + + Create a docker-compose configuration (instead of default supervisord). + + .. option:: --sig + + Generate a :doc:`/manuals/gateway` for each AS. + Only available with -d. + + .. option:: -h, --help + + Display help text, list all options + +.. option:: run, start + + Start the local SCION topology. + +.. option:: stop + + Terminate this run of the local SCION topology. + +.. option:: sciond-addr + + Return the address for the scion daemon for the matching ISD-AS by consulting + ``gen/sciond_addresses.json``. + The ISD-AS parameter can be a substring of the full ISD-AS (e.g. last three digits), as long as + there is a unique match. + +.. option:: help + + Describe all available subcommands diff --git a/doc/dev/setup.rst b/doc/dev/setup.rst new file mode 100644 index 000000000..6d6ec114a --- /dev/null +++ b/doc/dev/setup.rst @@ -0,0 +1,122 @@ +.. _setting-up-the-development-environment: + +Setting up the Development Environment +====================================== + +Prerequisites +------------- + +#. Make sure that you are using a clean and recently updated **Ubuntu 18.04**. + Other Ubuntu versions (or systems) will usually be fine too, but some of the tooling may not work. + This environment assumes you're running as a non-root user with ``sudo`` access. +#. Install ``docker``. + Please follow the instructions for `docker-ce `_. + Then, add your user to the ``docker`` group: + ``sudo usermod -a -G docker ${LOGNAME}``, where ``${LOGNAME}`` is replaced with your user name. Log out + and log back in so that your membership of the ``docker`` group is seen by the shell session. + + Optionally install ``docker-compose``. This is needed if you want to run the + ``docker-compose`` based test topology setup instead of the default setup based on ``supervisord``. + Please follow the instructions for `docker-compose `_. + +Bazel +----- + +#. Clone the SCION repository into the appropriate directory inside your workspace. In the commands below, + replace ``${WORKSPACE}`` with the directory in which you want to set up the project: + + .. code-block:: bash + + cd ${WORKSPACE} + git clone https://github.com/scionproto/scion + cd scion + +#. We use `Bazel `__ for both building and testing. To be + able to define the bazel version in the repository we use the `bazelisk + `__ wrapper around bazel. To set it + up simply use:: + + ./tools/install_bazel + + and make sure that ``~/bin`` is on your ``PATH``. + + You can also manually install ``bazelisk`` and create an alias so that + ``bazel`` will resolve to the ``bazelisk`` command. + +#. To install the required build toolchains and scripting dependencies, run: + + .. code-block:: bash + + ./tools/install_deps + +#. Start the bazel-remote container. + + We use `bazel-remote `_ to cache + build artifacts from bazel. Bazel-remote can manage the disk space and does + not infinitely grow like the Bazel built-in disk-cache. To start bazel-remote run:: + + ./scion.sh bazel_remote + +#. Build SCION services and tools. + + .. code-block:: bash + + make + +#. Finally, check that tests run correctly: + + .. code-block:: bash + + make test + make test-integration + +#. (Optional) If you already have some code you wish to contribute upstream, you can also run the + linters locally with: + + .. code-block:: bash + + make lint + + +Alternative: go build +--------------------- + +Alternatively to building with bazel, the SCION services and tools can be built +with ``go build``. +Please be aware that **this is not the recommended setup for development**. +Not all checks and linters can be run in this setup. Without running all checks +locally, it is likely that there will be frustrating cycles with the CI system +rejecting your changes. + +#. Determine the go version used in the bazel setup; the ``WORKSPACE`` file + specifies this version in the ``go_register_toolchains`` clause. + + .. literalinclude:: /../WORKSPACE + :start-at: go_register_toolchains( + :end-at: ) + :emphasize-lines: 3 + + Building with newer go versions *usually* works. + +#. Install go. Either follow `the official instructions `_ + or check the `Ubuntu specific installation options on the golang wiki `_. + +#. Build SCION services and tools. + + .. code-block:: bash + + go build -o bin .//cmd/... + +Tips and Tricks +--------------- +.. toctree:: + :maxdepth: 1 + + wireshark + +.. seealso:: + :doc:`contribute` + Learn :doc:`how to contribute ` to the SCION projects. + + :doc:`run` + :doc:`Run a SCION network ` on your development machine. diff --git a/doc/contribute/go-style.rst b/doc/dev/style/go.rst similarity index 97% rename from doc/contribute/go-style.rst rename to doc/dev/style/go.rst index b9594b1b5..773073c3f 100644 --- a/doc/contribute/go-style.rst +++ b/doc/dev/style/go.rst @@ -1,5 +1,3 @@ -.. _go-style-guide: - ************** Go Style Guide ************** @@ -100,7 +98,7 @@ Logging Here is an example of how logging could be added to a type: -.. literalinclude:: wrappers_test +.. literalinclude:: /../pkg/log/wrappers_test.go :language: Go :dedent: 1 :start-after: LITERALINCLUDE ExampleDiscardLogger START @@ -120,7 +118,7 @@ To write code that both includes metrics, and is testable, we use the A simple example with labels (note that ``Foo``'s metrics can be unit tested by mocking the counter): -.. literalinclude:: metrics_test +.. literalinclude:: /../pkg/metrics/metrics_test.go :language: Go :dedent: 1 :start-after: LITERALINCLUDE ExampleCounter_Interface START @@ -130,7 +128,7 @@ Calling code can later create ``Giant`` objects with Prometheus metric reporting by plugging a prometheus counter as the ``Counter``. The Prometheus objects can be obtained from the metrics packages in the following way: -.. literalinclude:: metrics_test +.. literalinclude:: /../pkg/metrics/metrics_test.go :language: Go :dedent: 1 :start-after: LITERALINCLUDE ExampleCounter_Implementation START diff --git a/doc/dev/style/index.rst b/doc/dev/style/index.rst new file mode 100644 index 000000000..a107cc6c2 --- /dev/null +++ b/doc/dev/style/index.rst @@ -0,0 +1,19 @@ +************ +Style Guides +************ + +Please consider these language style guides when contributing to this project. + +.. toctree:: + :maxdepth: 1 + + go + rst + Bazel Style Guide + Python Style Guide (google) + + +TOML/JSON +========= + +Keys must be ASCII snake_case. diff --git a/doc/contribute/rst-style.rst b/doc/dev/style/rst.rst similarity index 77% rename from doc/contribute/rst-style.rst rename to doc/dev/style/rst.rst index 7ad32ad87..5ccba8cce 100644 --- a/doc/contribute/rst-style.rst +++ b/doc/dev/style/rst.rst @@ -1,9 +1,7 @@ -.. _rst-style-guide: - -reStructured Text style guide +reStructuredText Style Guide ============================= -reStructured Text allows for quite a bit of freedom in how the markup is +reStructuredText allows for quite a bit of freedom in how the markup is written. In the interest of consistency, please follow the rules below for SCION documentation. @@ -13,18 +11,6 @@ General There is no maximum line length, but if possible try to wrap at 80 characters. Prefer readability over strict wrapping. -Images ------- - -Images should live either in the same folder as the file that embeds them, or -in a ``fig`` folder. Note that images can be referenced by any documentation file -in the code base, so be careful when moving them, as we do not have an automatic -way of detecting this yet. - -If possible (e.g., for DrawIO graphics), vector images should have a ``.txt`` -file alongside them with the same name. The file should contain a link to the -source of the vector image. - Headings -------- @@ -33,7 +19,7 @@ Use the following heading styles: .. code-block:: rest ******************** - Page title (chapter) + Page Title (chapter) ******************** Level 1 (section) @@ -48,6 +34,47 @@ Use the following heading styles: Level 4 (paragraph) """"""""""""""""""" +Cross-References +---------------- + +Use the `:doc: `_-role +to reference an entire document (a ``.rst`` or ``.md`` file). + +.. code-block:: rest + + This is a link to :doc:`/dev/go-style`. + This is a link to :doc:`the same thing `, but with a different caption. + Paths can be :doc:`absolute `, or :doc:`relative `. + +Use the `:ref: `_-role +to reference a specific section in a document. + +.. code-block:: rest + + This is a link to :ref:`governance`. + This is a link to :ref:`the same thing `, but with a different caption. + +Use our custom ``:file-ref:``-role (based on the extlink extension) to create a permalink to +a file in the scionproto/scion github repository. + +.. code-block:: rest + + This is a link to the file :file-ref:`tools/wireshark/scion.lua`. + As usual, the link caption :file-ref:`the caption can be customized `. + + +Images +------ + +Images should live either in the same folder as the file that embeds them, or +in a ``fig`` folder. Note that images can be referenced by any documentation file +in the code base, so be careful when moving them, as we do not have an automatic +way of detecting this yet. + +If possible (e.g., for DrawIO graphics), vector images should have a ``.txt`` +file alongside them with the same name. The file should contain a link to the +source of the vector image. + Including code -------------- diff --git a/doc/testing/buildkite.rst b/doc/dev/testing/buildkite.rst similarity index 92% rename from doc/testing/buildkite.rst rename to doc/dev/testing/buildkite.rst index a629e7225..a83f19462 100644 --- a/doc/testing/buildkite.rst +++ b/doc/dev/testing/buildkite.rst @@ -2,9 +2,12 @@ Buildkite Continuous Integration ******************************** -We are currently using `buildkite `_ for -running build, lint, test and integration tests for all pull requests to the -`scionproto/scion `_ github repository. +This document describes `our CI setup on buildkite `_. +This is targeted to the maintainers of the CI setup, and contributors who want to add or modify +steps in the CI pipelines. + +We are currently using buildkite to run build, lint, test and integration tests for all pull +requests to the `scionproto/scion `_ github repository. Overview ======== diff --git a/doc/testing/crypto.rst b/doc/dev/testing/crypto.rst similarity index 100% rename from doc/testing/crypto.rst rename to doc/dev/testing/crypto.rst diff --git a/doc/testing/fig/buildkite-elastic-stack-overview.excalidraw.png b/doc/dev/testing/fig/buildkite-elastic-stack-overview.excalidraw.png similarity index 100% rename from doc/testing/fig/buildkite-elastic-stack-overview.excalidraw.png rename to doc/dev/testing/fig/buildkite-elastic-stack-overview.excalidraw.png diff --git a/doc/testing/goldenfiles.rst b/doc/dev/testing/goldenfiles.rst similarity index 100% rename from doc/testing/goldenfiles.rst rename to doc/dev/testing/goldenfiles.rst diff --git a/doc/testing/hiddenpaths.png b/doc/dev/testing/hiddenpaths.png similarity index 100% rename from doc/testing/hiddenpaths.png rename to doc/dev/testing/hiddenpaths.png diff --git a/doc/testing/hiddenpaths.rst b/doc/dev/testing/hiddenpaths.rst similarity index 100% rename from doc/testing/hiddenpaths.rst rename to doc/dev/testing/hiddenpaths.rst diff --git a/doc/testing/hiddenpaths.xml b/doc/dev/testing/hiddenpaths.xml similarity index 100% rename from doc/testing/hiddenpaths.xml rename to doc/dev/testing/hiddenpaths.xml diff --git a/doc/dev/testing/index.rst b/doc/dev/testing/index.rst new file mode 100644 index 000000000..107102d06 --- /dev/null +++ b/doc/dev/testing/index.rst @@ -0,0 +1,67 @@ +******* +Testing +******* + +Basics +====== + +* **Run all tests**: + To execute the entire test suite in your local :doc:`development environment `, run + + .. code-block:: sh + + make test # to run unit-tests + make test-integration # to run integration/"acceptance" tests + + These make targets are a convenient way to invoke the actual build and test tool, ``bazel``. + See the :file-ref:`Makefile` for the definition of the targets. + The referenced bazel ``--config`` are defined in :file-ref:`.bazelrc`. + +* **Unit tests for individual go packages**: + To run tests for individual go packages, like for example ``pkg/snet``, invoke ``bazel test`` + directly and specify the test as a bazel target: + + .. code-block:: sh + + bazel test --config=unit //pkg/snet:go_default_test # unit test for exactly pkg/snet + bazel test --config=unit //pkg/snet/... # unit tests for all packages under pkg/snet + +* **Run individual go test cases**: + Use the ``--test_filter=`` option to filter on the level of individual test cases. + + .. code-block:: sh + + bazel test --config=unit //pkg/snet:go_default_test --test_filter=TestPacketSerializeDecodeLoop + +* **Useful bazel test flags**: Finding a flag in the `bazel command line reference `_ + can be tricky, so here are some pointers: + + * |bazel-nocache_test_results|_: disable the default caching of test results, to force rerunning them. + * |bazel-test_output-streamed|_: show all test output + * |bazel-test_arg|_: Pass flags to the `go testing infrastructure `_. + + For example, instead of the ``--test_filter=`` mentioned above we could also filter + tests with ``--test_arg=-test.run=``. + This can be used to run benchmarks. + +.. |bazel-nocache_test_results| replace:: ``--nocache_test_results`` / ``-t-`` +.. _bazel-nocache_test_results: https://bazel.build/reference/command-line-reference#flag--cache_test_results + +.. |bazel-test_output-streamed| replace:: ``--test_output=streamed`` +.. _bazel-test_output-streamed: https://bazel.build/reference/command-line-reference#flag--test_output + +.. |bazel-test_arg| replace:: ``--test_arg=...`` +.. _bazel-test_arg: https://bazel.build/reference/command-line-reference#flag--test_arg + +Advanced +======== + +.. toctree:: + :maxdepth: 1 + + buildkite + mocks + goldenfiles + crypto + hiddenpaths + Integration/Acceptence Tests (README) diff --git a/doc/testing/mocks.rst b/doc/dev/testing/mocks.rst similarity index 94% rename from doc/testing/mocks.rst rename to doc/dev/testing/mocks.rst index 2250cdab4..06d7bc4c8 100644 --- a/doc/testing/mocks.rst +++ b/doc/dev/testing/mocks.rst @@ -1,5 +1,3 @@ -.. _Go mocks: - ******** Go mocks ******** @@ -29,7 +27,7 @@ interfaces. This would look like the following:: ) For an example, refer to -`this exmaple file `_. +`this example file `_. For further information on the gomock bazel rules, refer to `gomock for Bazel `_. diff --git a/doc/build/wireshark.png b/doc/dev/wireshark.png similarity index 100% rename from doc/build/wireshark.png rename to doc/dev/wireshark.png diff --git a/doc/dev/wireshark.rst b/doc/dev/wireshark.rst new file mode 100644 index 000000000..c0713339a --- /dev/null +++ b/doc/dev/wireshark.rst @@ -0,0 +1,103 @@ +********* +Wireshark +********* + +To inspect SCION packets that are sent over the wire it can be helpful to use +Wireshark. +For this, we have a Wireshark SCION packet dissector plugin, :download:`scion.lua `. + +Install Wireshark +^^^^^^^^^^^^^^^^^ + +Wireshark is available from the standard package repositories in most OS distributions (:command:`apt`, :command:`yum`, :command:`pacman`, etc). +More details, and installers for Windows and MacOS, can be found on the +`Wireshark download page `_. + + +.. Note:: + + The scion.lua plugin requires version 3.x of Wireshark, which is not shipped + by default on older versions of Ubuntu, like 18.04. Use ``ppa:wireshark-dev/stable`` + to install a more recent version: + + .. code-block:: bash + + sudo add-apt-repository ppa:wireshark-dev/stable + sudo apt-get update + sudo apt-get install wireshark + + +Install the SCION packet dissector plugin +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Store the :download:`scion.lua ` plugin file to +the `Wireshark plugin folder `_. +This folder needs to be created if it doesn't exist. + +- ``$HOME/.config/wireshark/plugins`` for most Linux distributions +- Windows: ``%APPDATA%\Wireshark\plugins`` +- MacOS: ``/Applications/Wireshark.app/Contents/PlugIns/wireshark`` + + +In the Wireshark GUI, the dialog :guilabel:`Analyze`:menuselection:`-->`:guilabel:`Enabled Protocols` +should now list multiple protocols related to SCION. + +After that you can test it by running a topology and using a SCION filter, for +example:: + + scion.dst_as == "ff00:0:110" + +.. Note:: + + The :command:`tshark` command-line frontend for Wireshark lists the installed plugins with:: + + tshark -G plugins + +Work remotely with Wireshark +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Sometimes it can be handy to use the remote feature of wireshark to tap into an +interface on a different machine. + + +#. Install wireshark on your local OS and install the dissector plugin (see above) + +#. Prepare the remote machine + + Install tcpdump:: + + sudo apt-get install tcpdump + + The user used to SSH into the remote machine needs to have full access to tcpdump. + Hence create a new group and add this user to the group. SSH into the remote machine + and execute:: + + sudo groupadd pcap + sudo usermod -a -G pcap $USER + + set this group as the owner of tcpdump:: + + sudo chgrp pcap /usr/sbin/tcpdump + sudo chmod 750 /usr/sbin/tcpdump + + give tcpdump the necessary permissions:: + + sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump + + .. note:: + This will allow every user part of the pcap group to use the full + capabilities of tcpdump! + +#. Figure out the network interface on the remote host you want to tap into: + Get an IP address used by the SCION topology that's probably running with docker. + Search for the network-interface that's with the corresponding subnet. + +#. Start wireshark and click on the gear next to the interface named + "SSH remote capture: sshdump". + Fill in the IP address and Port of the remote host, as well as your preferred + authentication method in the Authentication tab. + At the Capture tab write the name of the interface you found in the previous + step. Find the a screenshot of an example below: + + .. image:: wireshark.png + +#. Now you are ready to click start and investigate some SCION traffic diff --git a/doc/fig/overview-routing.excalidraw.png b/doc/fig/overview-routing.excalidraw.png new file mode 100644 index 0000000000000000000000000000000000000000..e3cf57ab6530d10d6aed12e66c8ac19f585f813f GIT binary patch literal 35469 zcmZ^~bzECrw=Il2C3tWMlm>Tq2=370E`=5=?oixgC$tof4w_+DvtEs*L?5(&iHDqmEW~LHQ#5pEg0Q* zXv}qdoNMl1d#d1Oh!6+Gq0u4y4{y-$PM(CfK-{WUVO%*RyZ{LG|MiA}AkSza`~Ub7 zFF=|muCP1bWF+H%{PD|&@*#f_|A$Ba6Hg@=DdDXSfvuKt4|8eB74?FV#avG-Um0QaH36K31($js%bIVVMjz`jt>z`IR z@7H{<4GR`&WBBt0u75daVDm2K3akg?4jgs( zm%+jpQA;4^s(XSZ(h+7`RQ($=hgQd(76XsX?xst{SjR&0N(Z8~1WE<| z%=K88;f_s7qD1EdW&;K}0@g{6EsLIIIiE{m$Q93keYJn0V9pjb5tQUS1DWw$P9Ne4$_rM}FtUid*_9!yeFcOf_X=?Z~2etjMseTx$6f?xl|Z^U0PAhM*~obBW8zdZEKw%~I5YDG%!?cWK7B@8!)Oqy6+! zIM8C7p^9v6F4*S2vz$cwvDW&>PF={vWfDrt-zj_8=N1Zb(s#@r=Ipr2upV8$|EOnd zU?)lz__!R?LK$?YlfyxL%xU|iGu%kQi@HZu&cTX0Mzu`?LZr zpZWLJ(9R*oZo+^2NBJ$Y+^geq>=wC69>E1XF<8n*z-=G?x0D42uqrJ z?DI}DToYSlblwuIP|EHiCfFE#hjnZp&)Oj-OK8+&xR_|mtep0Em+~5>cqQ-C{&TDU zjuM?1;;^ktI5~J5`R@gtbhy8fYZo+AEwvYq>2k6x-~0zt{E=*M}JkrlFJ`LAHoXsHd(8aHBWGUu`q{)3n{I0*AMuzhc$&X)9lfL(G}r;54h^94@God#+8JlQ`Y4A2qI|A~pO`0{U9Q2cFTSen)v`m!wuAq@J}Buw7c(Kj%gQDy^ZqPc zAbV3fiCNSN{&xy>JkbW>eEUhPxbq1${HqM!Blg_n zbL{VbZ}@y%bMwo682Y@idO5FO5m)X1cwjsdyECwMc`T8`ww>+xg>a&y3)_D3VVkex z!@RCl)|qp(je+^xn(x!G^H?Qkie6~_BY%~*Rpa^K1>r@E{V>o|>e`1SDDO6*{6?@#`L;jz~i2|ccu zMP5e*EO@>SSdr4s=*3z}{k^|d9+G%`kYi(bpqG`?HCUs}Z79ZZ+Y3R;xsz@BmnNJC zeRiD|1jvX3U(K)Hlwt?oIUi&k_)>*-=dR6Xyg*^{E47NAOT87N26JreuWd$&8^;+d zf8UQ0Y8zC2yqEu_S zsXEH%is#FY^p}Ncn?KT-5s~%oeZCYtA~Af{Ph6idx+cC`TcX$s@l$)w&RK1B`gm4A z^;mLyQ7pF7dT8gsI7&jlCrg@~=7=FIfg;IE}z*21aUGum5%TftEFYDcW zzk{%g**NyH15SIdnGD|NOXKIdbd@sJY>IpbFE^3$3q{u-*p_S0D{GI2=jS=kK64(9 zEB#~+zdHNY>eeaDneG~^FN_yv&EMR4h=|%eroDRpZv6O7xP}s+%)W7*6e9V%z_7gi zZeOL1LgjA^t5RJM@5RyOwK}WsGWiV8!tLl|`}B&+ z98QMz*n^FRodpXGLzPkKOCP+O`kg}FBg1oRpQ4JcYgYFr#anEt!$P)SSM?1n`h@jM zAHVZd8jfOtB-dee{X>k%)uK^@D)jBm(n9_@k5q-1JxSzFS2%9rijhfKU_OL^4;0}w*A%DO6Z)zi`|!-J+Tz! z4o19Ov}3#bnH|xo0QqcsGFRbOcl(F9WATNyS+3Szp$e=Tb(s5T=KDQtP^EabP~PXA zkj!xGXv{Kdl9FxMQyEEA-&^_RYvr0Z?K3_Gdm z=fWe*IwM)_6VW9_u_DzO3beMntA-9==LzrC8c)~|jPFLB63!>YI&M$G#D4kw!OyX7 zf7oJ6X+IFzli=&P9V3IJJv+D*kP-T{<~;B9xHMcnyBMtvIQS1duVY1?3S(z}JY&D} z@|owc_t8FJ&-*_6C^oGAyd*)A(=ecr(o^Lo+AY;#YfRki_``g_cd3AKq0Zj!Y17(v zZHM&mE6&25pKn&vQfk>wWhLUn{F~-ml8%%F?I z>aLF~oN`H(rTgv`JBx15yWP8Q#BPTetDzJ_ZsHheBL-|Zf!F>wJyfg0>*%W1Zi}X2 zA6(AQpj8PNZ*qK`ocBwMd12MoZI9cJ-NtBEyuMNm0Shjg5Hl3M01<&P2|nvj3k*9M zaRSiK6BJo>ErV&{f-QRg{7BrReu@ndYn|h08UO*Jk4dzRJhvFZdJmWqvQC38t7kr);!G#vb`kqIWDp(ewwUUzR}-M1AsMcUAKc08z!v*M4%mVui5=i6to=W{Xb z1HL0J)R5qTihd+6s7KkGr{$F+x2=`^3HH9>ie$^+sSskL#&k~m)@<*irthMfR=!KE zQ}kTNt`*)qNfo@fp2b2drOcpH&r$zvk|@KBTyC5*i+XhI4Wui>!myATog8H;0)6l|>}$KjIAaBkfJ|9);IcK%F?KsYij}m44Qra#hw|KaL6}=ktn?sX6-9k!9>?tI+o@ece3k8}d!4io z(Ye|R{b^eD59R$$!(G&En~g2!oO^@wLkItsGWdCr^F2&3PPgvAt6)6uZ^aNcdfeCM zdw!UBHkc>3xeB7Z$laD#_0l;1j4GVlYODaGiCD6qu`gcm<#sYm^ey?#gwHlth7^uS z?QJKj=w$1T$T7pg-d=HzXlpKq0SA$Wgr)JrA7bLI0R;Q*`?cqLf4-K(dVOU+w_Nhw*!YSgz5N64(7U)g- z%B!y}TGKXP+x?#SImWBsN5N?v`5t>4JHv<+;YPyrhd}<5PDCsHD%>1YCef+Qy?|af@|7ffLbCA?siC?RDkY3$v(l zLbPXi{D57eRItsjzAlflGB(Nbhl-_Rp7ezW1oN2!~|vWeffRZy%h5 z_qS4nngJS?dfT$8Xv*yn__lAZcI*lO9MkmT%l)D4yn{WvdcI0jkt~LXO}}_nOO<=w zr0Yu+J))s$XkX_<^=+%9X~=R;p;l0S(9Xu$LhClq*a(adaW6gyW zjM-d}c)@3MHHw`L(q^EF-E=v>nWJ20C66`1f;Ij>G>E4#h+f4+VX zTVAFZ9+j{1!wK>skJoD*9-EaV-ON`@HWl0B?(OGv2bnO{$Akip%QE5rbe<9G|FH4; z;#f21?(M10cuVU^2phAJD-vAa)tG~yGkRAujD4>Ct({S^j2ZxUgEz+@l4=UT#-~^+ z8LpmrcRyfyII4`!1N#koGp-0oLuM25aD2U;;b7EVNz!R*OAGc0=r%cyL@@g_e=FKe zE$z|kH>x%*O+;;M6M&CbbY*)dbfviY>L#P>NBOCLaI~yI_^#lraJze3JyuZbLDSOQwQJht z8d|(yWC3f-lXub+|DjF1)bo|Yv(^YUBKEo9l z+Se>}JY9~hJwL9gu15q>ox-R^+l%+5KoByxjrfY+r08-e43-Y?@bO(|Pd@{huQ9@m zHZxLt@7dDdveSgCEP5UM$nbv{@Xv&-RFA^OZB0Y1bdsd0!jLyXaOsI3iHY;g2MHSX zQj^cM`pQ&6mGjipDIvd@@Q^jzCld;826fA={C< zL$YFbQ`?1!DvZ7Po{^4;FQR=$>bEJ5x6aS^bZ-Fp>f_1n-A&Z#7r%pWD7{AV<&eEw zUN7QH<|Vwy9d;3WAA=9MTr-!qX;VJl|D3>s@&)FEGtmykw3N6}(Jv+w&l@Zj}{_s_(w$ zNVdcMi6%_Yn%tqiSOAtCg{`z33F=7^S6r{dHB(?3u+BC>;U!CcQj4orZka5>l1Y48 zmCja{*|uhkw+5a%Cml8!mWrH`UGir0SH9OP4aAK9|Ko*m)?n&&;9KK`*Y|(4ww9DQ zg3vN{FwwZi>S>I7(jhQ`?dyw?^cUce2qTo{w+szKwif4%XgKG``ai;C0nA=_xcgm7VdGs>?MGqaT&+OE%wYi!zh?sNLHt|#}+@)I?D0&vKo*a zzwY_zo_L6wxvRdh=Q0n*J04ut-}-- zGRB9n1{*R)%OMyfi}!Vu7-2lK4Mt{kiH-+^w>dO_{PMd$)J|0q6Hfdm8>rA0@m}Yh zy`WpE*5IDn87l|qeU`Y}H@0jXMWiqA2r(ITS##+2i9`d2#-3ZrV=uH$UW{?%WqNRN zKVkIF>pQGudi;r?U2QtqYLiEfpa||fhS3!BAD!S3^*G9_%CO`@7vY^5{_Otj$z#9k z7EQiInJ&wO1woKnDin;II+0O!aWzGmVc+~gfV6+U@B>CZ?jCp458@f02_G#`G z&Mgg&r<{C3{acQ9zD1KDqrSo7Pupo$ylApR`v2skA0T%`&4M_zF7}TF$agqvuOmF4&mSSP(6JrA~9Hdx@zE4 z^*c+{ZcAiW#4r4N9y5=BCSZ>{&(gcxviA2qADR1U+i=U>{`aVSx2vC4d}}xTe5B7@ zbR@Shr@_}dxoR=WqvgnFM<_+)d|V=jFD>jUjfWmhOdaFJf-2Tarf^%#dwE>kl%l4z z2-O!D5f#TA%}{|T>t`Wd?-8zX!+SgkeK#eI0FIH~!^>*C- zOB{nYofSiN$4<7lTXxss*VjL4V!z{LOka!8rT%keu}4tHL<2zjy3_uEs^Kf0?FiU%%8DOQg*HZjTo%ZQ6aK2{O8yPT_@FRBK+z zG-(xepn?>yu4LlZ2%6HJ95wYdDjVD=>vI=c0{?iPChdUVwl8NFQHUlqj%Brp&-``w zi}P)AA@{#_MEf+KVV0Qnb_u!rFUPSiRH|RX59>G%tLNF*1Vk5!IS&@MO()%$QD?Lt zyWE8v6$xoFUxtxkCA>kh^~){-Q#omT-S4UyR5`AX#hbiYpRlt>TPg`vMY0E6+QC_F}MgM4G zM;G2lZt23n_E!R4SBNTxG#0V5$sXD@u7}dT`#Fz5av9=nW)1wvsn;NFy;CfDS=xQK3d>zqZ@H{E zj#ocnMRCL}3?^)z#`IUuzDT|wRmkLv8NGS&O8&wgS@W&`+YW1yFBU1khMOvE3#E1R zG%|J4p1^2RX?(3?x*0SA(7c(TSaiDx+p{kaFHR7j=nZLBRvbmgHRbzZwe1Y6;<;1^ zPK@Cu`{r^NOpYh-aC~>AUW`=623c0Z!B#QcR5*mp!1<52Dg6v>a>&_dIgfv>uo0c- zK}qKqGpcOy_=d~abfFw+zPBUB_Ae?gh0946clpggqB@$eURJd!nchJ}AAO>D^hrG4Q0Q*E(`9gh^HE@;%i7q}yQB{|^^ z^FQ$BRWq^M7mU1lypP-5f3i*y$+v*Sf`e0H9;-v7Kq~5J*%58ur2SC!mE*WCKaj1# zkYm_c?5Zl3r{jL*SV4nz6Q48Kof!%D>v?k#(Qx_TtA#M@fkai&CV)>ZDRcj3w2Wa9+`{WueV#b7No{`!E5Kq{_Lulg0rB;Z zkd@80a81ED!f~c+=Hn3N6V`k=Thn;_Zg-U{@sA#|Q&=&A>JB+v7b(-C?D;xkPp7eL zeFlzwgds}tZvuBUSI4d>55Z@>yyz%gu^C<0MSN|gacb8v5=G`o8g5P=&s{^*2(q@& z%Pz7W@xKZ4PaQseJL6OFQf_&vO>8J>5!8iP;!jtaxyM+DXS^DGRA6-&Ht0LGnMbf)N4NE2yS8*|ig9B3LPj^; z#6;ELf5;#v{6T(VM49glo()uh3lCfMpy@XAMG?oqtwhqw1)j@e8pe%tM;FE=`lT?7 z;p!{{Ozy*}i9_1sbS8f4+CoLAqu$0zqz|O;czij7(bNKR8;^(6feIqt4z(=M^lx-k z4@nN7l*cehY;U~o)r~uPP;~r+_e9j%>#KOqeg=o`OXVdHHt@Qh=p><`=Z5&3Gu=mm z51)2~)|!C(m-9g(N0z|lP?L$w68Nl8(}@Dg2o_u<6)fs*^LR`w^G%F=Y3`uH&?Dz> zA&1nhzXvhzui{DD&HsKkX33`q*MuW2^8j%6Y4!3He{ZK9sT%=s1ib+0u;MY(X#w(G zk`{D6=?=7A9B_qZy!L!8mg z;q!6Ez46)gafSczWg3%lNg&&6fgdG8@mBR@SMi?19ka#lp30!g1b{ea!UsA-E51y} zeiANsnexJ`F?VI8JJ4^S*VJ>5Tt{UUf2Dxe3kU4dor8WNO#RxM_7e&=IuY&uy(8dG zPEVUbExV}!Kv4x&V;z*sq3-x#W?0E_f+J2;rZ7coDl)?;&TW?AkLzd~*}J<{;z?Sc zTAzK91E{BIy8qs<5-*sBQQdT+e(`TR*Y3ERt7ZW~9)bHvQzm4R;nuH~A;9~=pv6dd zCP+XZnp+T-Zy`c=w-&*wPhrp@5y-F^VuUh` zivv3)xUoTrW+R9}x)w_0gm>Yx!ugQ*0C|DOSmr#r35{T2WcZ%!ex*+VRL2&@8O497_bo-$@!8` z^)L|#z=7Sm_en+y=*p{Kn?GJIu;IRnsezc?L|a!zO9)Ym1CItV^+_ZxmMr61SX&S5 zG!Q=kZVA{`S2@nu7MD!Oq=2^-UUT0u(gIT*qd)miVH0TO$QuFwq%9$fq7gUJ7(hVO zyv@O;6*C$>ROhJ!Ni1~Twh&+TdAnm9v?Rtq{4Khc%ioKvEJVn=|VkYjjq3iogm6RL?*Ou|v$02Z_`B#hbu4gUPj=tG*u{6d79ar|^@n!c{DvK8)gx2tO z-U*vzF0lV5Im8WIEw)9!+LSc0jgT`TSgv3z)GUY3dlDX(++;AVmz#Yf)2ju)MuP%O zgu3NK*^861pKyq(V2gXrcJG>HE*-N*nx;bXC3UWG6=-|(UVWyG6|VL?v@zCSLWA#4 zy|%})5Fm*I?^8~}6NqQKFOwR);gmFtCvZXyZ#@wmB-aF@zj!)jjGT{a# z(!q#9%d6g&ae|JtK`|W6dU??}TjN|L6ID5Od0yYy3Mf7Ex=4DC-1QL6y zf#fQ|Q#6tYY2pw7HT@=OxHW=~`bUygObVM&u-8Bh+MoX|`M+FzHOfT-?$Edb>QtA&?0w3%MR8VaK zTqVo%29>#o+@)PImZi^>^><0beeTr9rDkOOA0`S^oyLI$i9~mVlFswR{Q_f5nR*w( zluM{0yAsmHb#tkSj+uDsWx_4K&Qs9y+hGk6I8}C2UO(x;YOF{x*FA_?NMXEKF?BkR||QCI%RIdRQg$|gjOu@lT~hba8#@EMz6k*lS^l^1ix~G zoQNPC#rq|vms3Vavfw*9%RMw5A%1&0Ku+zaRSt_{-&xoDHrqLfo15KQ5nF_g+nKKM zqYu#jg1xwcB}oyB6>C{OGcyF~LItf0Ajq}zllzeGc7z{MS|fuDHG*#AFU}O*Ol0lh zj0}0@wwE*8&h8RD8qdMpi$he^t_L&puHa;Pxl?be+SgMtxWq|*C90A3t4sH{wAs+t znBo-%9+DlBBljF-EgbK(`O-&ZK$yA{Su|!e1X)7!4TRm(3%eE6_v4E%d2@Efw%6LO zS6d)&=ay^fe|Ge%*EfTZ!YoNC2WntVkcu0&3CDBq>Z=%*M%;ow#HiAA44%~S6eF0A zHvUy`3F9ZG=#~-~uVPS*|M7VoKZU7}nc9)WrFsZN71leU?}@dJ%_P)`Xu!wx2k-J{Gy6so zQ>{V?Zs{%@yu(Re`Q~GV)nQA?27j>&c(I!!Wute}`-H!Jvx1YMe_ribd3q?j^byb*js>!-G9@7lfgOE&nL|HU1!JHt$zX z=6VMeEc-FE(8LXtHmYBHLJ2*x<@I09rd*#(>?~s5QJpt?8r6<0(UAvk&r7^HXSp(b zQGq;5DWy{fi6}((ldTT*X#5`nsy}d!Rd)ZZ@8i#oLEkP-f1fXd5!Cx7TWHv^bi-q< z&ahN=6@=j-=mA-tQvc-MjL{>bQ*hEM|F?m%m^gq>@`l$Eql)^QLN#4vw$GcHIMe>L zRskZtV-cL86tzH*L9lD!}cX}NUL)NcI=0T5~>>6MA5Qqr8GqyqjAqmy3 zxHqsakatA%3P-h)Z?pPMCAc}1Gv4YfCwq2D-Fbx7T$v>htP^N(4UrUEkum7wCm2K5+zD+1d3 z%~=!Fi)gJPeT6tt8_B_Tk7at#gV&%22jf37<3O?cO&WvnUDjYDv_H#&+j1@kgcIeE zRo5rvWrZY`^%f4VhL)8daZP7Gumq8JUXDKmvScaYRT92Nx&y}BVaDv2UmxwNUdfe} zQ`k_b7or6AFgR2KwsOfmXryInw3jBhRi|*{Ne!EpP}*wH;2S#$NK8fF5#No;ik`*K zZHrhceTzn!!`Ulzu#sv`7p374#p@UsDxMhBeiI=Wzo@;u_+?sD-oEs(BlZ4L^{UlJ z8&lpk<=DH-g-ru~qhvR&PWojrm_ zO8r6mo!&GgWRm-URt2KwMisKN zYPlpKFHXE{IlXk+wNMQ4i@T|FmxsoOQT*IuVfTg*NIS1GocaTmz4}dtq&=3}XWF$u z(N{HIqrtbqHm}p9&(wP6ul!^IXYCF zUr~6fv7Vyb&yS(snHyJ_3u`QQzlkBW@^NNnrjuh>MhC3c5RBJI#NgatM~n668lb}d z7vcWfw{HzkWVfbJSM$;4*VU$ZKZ^S6b0nIWAS57s0A)fMJ|zFiT4l0A7B@bszY9!< zT(F=O>mjCZzR5n-KkuGeQhaT)ODpf|a8%8M?}m%K(==~)8Ad`TH5&$|b*2_VbTk)A zWibfy+wIKN!t2SA@}I(#FoSAH$O`Kt0*j=5Zn7aW^AFWFV&8)rncme zHqire0h1OK%N%!!M(zrPtpHOC^)psUQ&ff{DA)1A7JSj9R}M7|@Dl;21xA9rSQ66r zFR)Asx+{9DZpB9{PQVYc@@(63-ztpUdskg`OTt}!1~Spv#~f@#LM>K?C_iIMrykT*i#FvVQYT0v+z zR4s^Yp)e8#|$I`(g6 zA293sz`*h4x_OoOkh>jN13<_=D}2svPP?gJm<@4!kc){$WL)Z39pc*Wo(f3?Ro&=8 z>^w#-nIGqQSFJ3PMMGTh)=fk$-=-t}3BN3Nmm1u2&zEhX>rVm04;fxshPt9T`2if4 z-x&dR?_AdKzd%F6b@Id}X`zNTwH?t`=OQ9Kf}elMDy8*+K8^`e@6ibFzU~*H=oD5< zEIkzL$@Vj$_?i>moKNe4l7W=B?*O4m*qDm-b7{)1vLE9^Rcel&{b`U}zHPl3;68nP zNn%HA!?Z##mlf_NQF-8gK@^XE!Dp#U7KD|x)yR&r8!{i}r~q?jy3HymduSWPxW96t zi_DuAZIMt~6)=rdB@0Kl95o*_MrD8WBw&atjObv}e|pQrRS<^G(x8(*OH50^6IH}6 zM#-6YTd4_QE^nR97K$*BM`;^SP}}!J@<2lmfnGyO99W376=Fk-Q%zZPT&CcN1f!@_ z5knG8t-EkSGaKTZ08tnd@Ob$uZ|AN+yR_@NxNgvrxD?Ap^>;}K%jm5Wx%diY90Xc) zZxAER`q??w_8p)eu9qExoU^S|mhonPoENYXMEgn1f{Nc+Gv+m_fy^CR0ZJ&OszFU* z`M=x1P6Zx1L|iJeO{nVNjC%LbM}8!tRrO%3uPI%T;?u+oN0R50lrUlC598v^jnCSiq=>@%__oezF_eU+Wc}pGr$;dra%X zvKg?OarFgtSj;TR3YSDf(H0-yam1U_qq*PXO6*}wWE; z>Ml@#svIi60W|%na#*mSm&jiXVuQ;(_<@@le`Vg#P_A?*vb<%ZDN|lo?7;6|raez! z&I_S~UIs9`yaiPwppz{#F1be51)kcsPJg}7@8|Z#XkwKttyrwKQg&hcbssJ;t;d@d{@0lJ}}JR2U-V2$2ZqqBb^D2mLT^z6v1@THC&0mRH~ zz0{Ly`8KVVJ&Q?Q$xKHbhKRlSW>a6~sE2`y!UEyx67s=dGkRJ|0fp6Ci`U>wB1T_61UO7cUvd$5@q?xt_9Ttc2kaxeCoqvmhzxC{u8%iG^DP3zZLuL?z!&gmMk z88lZqJ=d>A`>INHhA6i7VPMHQ%;&uhC)NewFkT==o)pzdRtIik@PGoAI}V&UEq~C9RLTyiKyd;7O|c_aUQH4xgV#D~fa?dR;P3aDL=(Q@SNtWd|-T63Iik zY>CUS3*q^dY-P8ao&gl^>aUd$?7()93j)LhGU(9iFEB?Xnz1l>#kkZZNq&%AJOiNht-;M8IMoft7C#Tu*CLICY*T z8CL*1^ulYK~VD;ShYi|#v4SRR*f0kht`vKm2e6sIftTRzR{?n(2y0_*4_5RqZDD$ zMOSF+6Od%uN?p`LGS0S0FJd&kElYN`rXXLF%%|Px4R=Q#a?F8e8BJ~fO zUd$RHEvT7{hAbJcwN?quH>_^D@>7HuFw=YC5C5706KvL z3MA!%V;qDhV}ann@+XkyjcuxI>7jB=qM(PmNBW(IP7#Mznerzy3s3|gcq#gH;zqK! zGo4T9su?5A9sBi!Ym%rWd~luLK=>q;5AnT);diQ2?!AKf{>5UUX!opbE(of6x2yn0 zO#V=6sJ5+5pg;j@J)lb)=$PfhvC5Rt+{JsfMe5$4Gyx9V{*bD<$xtTz8LL!IL)Kw0 zLv7)q;&{2-B#VL`Ds#+f{kKcOBA`hE(g}`i@?!r5F$4NYdokb_RZ)D4&Uz-9 z#7eQ2%AsL48%g0P$i6$P+_darPa8OnRzxbOBk!X9BS(ckQ9a0xLTkoxm-n=ZI#ps! z^Bov}mqVq3CR6A~zJ`7(V=*-oS6MTgIOYHfC=0`C6UAFU-1hOEXd%O|Z{`S(kDQn3 z{gbO12t_uZBp*>!1}@2=Z1lC3<>1P^7an--|5i6g6cG-$ujybzoZm_Q%KLJQoqF45 zqC8Q6c1M7uc~Ifl<{{%A_b--rAp!?|JX}5onjyec0Vmp8^4Xc6q{d~4TGfy$9&KB4 zW6lc%8q&hB>8QgFRay^S1NOTir7Nbg-*bhm4`RN6Fi1lm=fqinq5F|Hy_I@sBP-;(Ji7}?7`&>5zZ z7SZZvx+*mUGefHf?@5U8TBkpeFWjfIOTSio|JwPqLq5%{4zKS?2A|M@s9vyph`ERe zKd~VqqZ+UtO*DRkZXT2%Uiy0~7fp}b(;bXC3}_SAtu#>sF*Hi96FdK!HCz4w!(W|K z_VMMk1qMgj6+J`pkMd*klA z6%?w)c-#XQ?ovfd#A+M(cXP5?x(5y9!Aww4Xsl?F%J$NUSHr!WhswTh!5upeGqOM- z6Vj5qFSLeVhE1g(o$Z`j)hW0t^6J#6N0`}HST2f!?9vyDdG-Bp6vq!$^=}MKP<`NX zzW92bR#*0)A8R*CRGh}_bhR~4p|g451MP6siOOwt&ao~?QkYe3!vS<7Yda4MrDRhd zy3wwCLIS*FF8HDe!*LcX17HV%RWO;Pf`$A&nl4?aX9e$>6o*ssKn0BRI+{E}z9$o9BR{?&P_rLNXqDJ-hv9&m}s z?D^zzzdGt7$;MKUibG~Ps*in}6&wxfXxByP+Nk!wy#PpbDNh^z=ZI(Xu1669r1tIR zW&5<-cs5~ZY|d{+@990r288NI(7F{xE`vg@ZWpc}#m<-Hj;~8{WIZD+1#B%G+r~@{lu5xz#so~HL*)?Z&?O^gq+8My7klR4A;n#X z75JIkONLVKK#FIby&z_tKU+naBtTC5NCMpDUNEi^ytfDG)CX_uH8S!zY^fPwdm$n% zJD72DkP)OZ-={UlEKlCDs0n+t$}nt5e8$E0kD}-cs#53b-tZhgW9UPQX__Nud7yuf zpE;BX3gj;E&68Vlujn{eI{R~`p{l4A zsDYy>L-w}?kC(%GR9cQoJ{yXP0r7ZETS(k8PCYe_m2uZtAomwS@|I|8sCx)JSr3hq zv(WO!Wk1;Oiz~V2(SOU*Ic#DAgThvFTnTlnmRGS#o4S)b7gZ8Qzrj-Zd>F_$sqJBl zxsCGMMXKrF=LYh16{$9q3_Ui?sRX|&G(ow0z1rTSsK@+XH_h7&j{|O-=Gm%BK|Rgi zSw!*95hV#KkVuC+u3IgxemE`~18_Q;0nQY1B&r)|`D%mOISwYrakencP#=n4zrPU#yahF zNd0%&oV7wdKgrESCL4AMm-?TDb8S%$7MNp`X8ZSdtq7bDO@~cn)M(3rZ6J&NjVxTl z{x7Hb6`=vPqroxXDoC!`O$#%k#?tDefah2{f??`VKHoX#mY6VdUV2{~_f0Yc0?*Dx zVg^%6yfaEOqkeK778 z*X)6heYn!OECAC*&spXktYD5$zhpUWSNH@tt6wcK-!&S2S{+$m zF}2;(A&|#>6Pj>>w6`gk6JQIM_Q^%CLz$V#aQNx}Ywj$=s_5EBFNnB7B$duh_uh0# zHz=j#rdzrjB&8%pL`p&dX(^GE?vMthyAc8DGqdq|{_lI8^W|LE`EdBa%&ax*-fL!7 z-|PO}OlwsG!VDEfRJL9sWnURwu5mQtEOq7-M9B)W9X5i2tzuBWF;qOUa*ydf2^uXo zZCdBRmdF&XkD<&W#1AlCP&?i*GD$i!p2nyh1M|OzLOLOlx53dwJG4CCO^BlX>1?va zae7^{irIs(GB}K-g+$|kp-Yc1Y^Q@lN~}d#zxQzSbXC5?3L>RoSWYk1_2CZDhy!bg z2kfP6lkMKOXs$S>&tLTN*_W{(0ZO0bBSzMiP8(~8D)}zXh%LK#m(lM4^FwMAqXRxq zKF*}UXbcyer3kJzJ@WVmK>I&J%$Si?OsL4fS47!GwnSb6ai(PP>lmaq-c~;z*HjOb z>?5<%FTEcfS~hAJO|TSZ%=jZky?-AQo)Ib)^#%TfX{rhq<0aF-)K295@PXPD0NnxP#D??c#so(>JIBzV*%MXwDkJS3` z@Xr!?yC|OrX&d#mWG3h_3g_fRJm9ilFjxMCP1{QnjwN(LMii5OpDe6DE4k)T~mP7&64m!5q*xxdCQqE~HGWL?)LvmDNp@}a8QA-ngCq^#^C_s9O* z`g-*pYS$9xY#&~QjrIPReVI?8Il$JqMkj7iPC1^_R)kI6!PX-@RT#;eX1np7YCaLe*Qk3cX)ATFJxs#k zJj_P%%@HRUIXym6U2qZ_@(`b`8IggJgrw|I?sbxx9mhq|wS8h*uaFA$N|FsMoQ#(e z7_igi{2FUK%aX2~_AAPVT6-~1+r5gKATS5J^`qHxpQfXO| z-?Cld;}~}`YYb0=xfW8zjsz8na$?Gx3)NYL8;SHg%Z%n>L6Tu4mL*FlN51B`8B8G( zW^S64OMQIQZHj$P^{#$ExglkpMq_?PR+=M1c0iEvz{gjn28%$JI@o1AtgXzOQYY<@&a&tdB#UzAwYH+z=A;^{?x7wF&EQe_wMVUU(-A+mtgz znJzePrRo_Iq$NAF`+x(ofhbX)b+)FJjdT3ko`6a0)JEgLC2PpU6db{CsrvMGyY8O{ zdk-8sfO#|X5!SwFq}Psw_|0KYR-7kYOK{4Lm8!b0H6lb@sHKx%7DJ#8*TW`y6(k z)gfW-UR{!7p~Iv}9S4L_mg9Tg-j#~rLur;TqUQAw>P2W%zo(Lc&Ifo=UABZKD&|@2 zkuj+rVZ2dGr={0ftD@D2Z>O{o95QqySSo-;h_6Q_K)i0_m#dYF%K7SU=TxpArh)Z@ z{Af!eEtZ&w121|!T35zLV;}7|!tM{$_PRz$&)JgCh5KDDz0i#M=MAEXXCB;d3Qah{ zqok9K%16&wOrq|UD6ssE>9F!DvWu$?EeI+t@G)-j>@DNm!7asV`30WL$C6O9uQ)nf z5o@e2f|W}GvlN1+tmviN>LGbSlEZ6%%mhQ0T_SwRmAvd{Qz6QzD0;VK1pCg?{wUPX zlyTV^mmkUUOytV6eS%cUQwwdZnV$lCxQD1v@IGcs$!NuBfCKloDN`jHvo#R&{ z5s!pMPxqO)N zhWg<)+(1ty;4NXyX<9c8H9n3+HGTwVNTdjXp9>4yhlc`8wl5QT`2TLSQ~Q9=i``RL zH8~CJnKolgBGH1_De|Loktt~tbrRP0lnZO?(xF~_jfr(iZ|E9`OsdjZ&zF88kLfcx z16_zfvsyT)s2LF*mw@uBuzqHkIFBQtfvSfL7sfVp9zXA0)wOi;@cnp_P!_HI z-psV!cVPU2Tt4=S0D)|Ry6)b+TucvpEbPOId2=d1Lq zXu8A1&lk9`t7Vz+M<>}lH#2w)mkf@4So?_Wb!o#;j3j=TEvFJicF_Tz zh!YR>$L`#nLxJS4C9H!vY^x>1fz>~pd-2P~H(DusS9>+spH9c_Tl(y#nX`J4cC!M|=#Z#WW>~&(hH;K&CMqe7zfyMeyl(Y{u3aT5 zH#MDF`sxPTDs(GTIt$o>A_6sPT++^}IQq#b61!LaR%p0p`GnM?%SB6n{VTaVD;#PD zw@U=bIwR7}e3Jq#o@s+SGAs~N=Qi9{{tsj*f@q#ccQNkZz*~)QvV7rh;(24{7M?BY zCrs%`R(KEJ`yQknfx?_NG%E3qS)n^tTId|5|9P|Vh^51x;$~i%^pCC?_~UX$rIx}*O9Pb( z`_rOOJeb&9rJ(wyh6=Y{(Tg+XjW(xKs8LChi09-%_L8quScrU$^`Oj>?@KnD9a-@K zMr@J{SG-(S1?hBehfW+7UGkUm4oeS^mUO3*^T2L*o2lKNYBF%ulQ>bNOJt4tCuF}* zcuXQemQpN{Ie5|?r9-e(Y>%o{u;nryl3=7WPdos*>oY@v$D|v`pZVG0UTDq*d3TtI z(R%`P30#b9ip_4lj~-EXTYs$KVKo17C9Dp=9gp|yhc#VNqR z*O70~=((0_)_jn1d{kkLdFM`d$g-l2KO|f|uCn(}RBp^Ftz}gnTL79Tw6EKVXVqj* zep%5F%AY-FYY13otUg3xoOcWtD0ohfq5s5yJ?~gq7i5(!Zgq9wuU1OQ?snjE(DDbGn*J*J#dmRL(UxhnCjkHvLoVP=Tao6ItSHp}Z5#>MdLdek%kj{#iT3p3h|io^S_^z^ob@rJeq@OS8SO7GJ34r_b7z+pN-4I^H7bc zl6w&cy`tMl1#)1Pt;5sZL~<-YCc_p5&+9sAt82iRR#W7P$k5lRn_~VcWQKw1xc;h| z$x3_%MG~650NTEKVG@s5KMcpj?WUGPQEA%2J|3F`(JtssWu9SwA{a9S_KTd&;=^y7 z1$svaLE>vqB2;`$B3R;Fz6l;~uJK^FEv{gB^=M?MPdezqiRrN(bW_PNQxihJzV{PC z|16Ok<{kAFcPj9{)Z1{+p?JFm>SOdmxt>jkEx@Gsp#PDg!11JRuEDky?*r1p60p7b zJW1^4JYr)0G&G2Y2HIbb#9sm76us6e_>n5Q(u&=~Rc|#481!qvJ=q(Ot^mfhpJlX$ zc4{>xBX>Fo3z}6|{ko)I*|Bcz;fr)dfnfMGBVp#N?Dd@-7SN7 z%zBE?p@$-Q7XbKcj~N3RJTZQ^gS+*uWtZkHlinAQTNr`TK9fC;fPVL35Q8&G_$?Aw zcVCgmA;G3(fR%%;ogHqvD%HIWpL0v*0C^O%;1Chepj=6^O_z-$VVee8Sxn1DZ|zEj zw__x>8+eye`wIJ;ri?+zR}phao|Afrd{p8Sp#oge^2~ub$UQ}Sb}Zw`Q}$1&5yt1i zC(^p%+54j5>@y7NfGs#QcJy6X_Ry}B-`fG(3ecoM6m^7$dT|H$l`|}t27Y-wz{r5w z3fLDqVMRdFE2W{1azuGI+s~=5kvp2p8K3O}T}U|*1J(J;+P!yEV;u(0VSZG`jI)9KwliT@EOlD?#B4V{)}Ck(2_alR!^q#yfW5a^0&M^ON0&5ZkP!5*F@K2 z?tZuP@>oAxxHdUK+Knw)vp}`S z9zSrXwo?1@VI5zKZ?&AzQ@&QCI1eTlC;U@hqg;8{!FlEd5i_-lxS644pHd6)qJbRq zFQH=TcpHh3U?$9X0%jYics$Vu*pB=i=?MUT1%Fs7SM3ArxQz~b0pY|(iM*_A)5O?% zMv6ZoDUz88`7QT?(wcQsJ)!2Fp@W%Fa(&Z|_)w#DYNAc;Bc#cC?P=U^j1jNX zmE=LnkRk~n4@F@wV3sozOvfYm-GIqaxe7s62J%$|zYt+f;~A0nWM}4A*T{XH-+{Dg zp+Z}psPIc!a!&&`JUFIh?fXWY0njxCs8QWZrdVnXY|%gSEuU!hHZSlJi&~vo$xv3h zRP-!9GCMn``TpuQH?WdhP_CdnEdolDHUWxD5LzQXs*2JqU~8Vd<6V76XzZpTy^FH- z+iNX-0yN$vD1B{3kIkjf7@vxK5n>Pks8eH2d6X~53)qJB4Jo#FV6J^Mnrq>U*|I%Vyen}8jbcz9*Nv$%%GnrbDCbP~r_!wT zK0ljWsLIR&y!fPd4Il@)THPm<@FQ)G*n(?U^?&wHh=#S0NEHhhhYt0 z_zyz_jwE(5I_(vCm|X{)tU$vvK?ZK~$7r_cSxo!#E!OX#qdHbOOH!GDb<*R*;hT4M z3*|7-4rf)pr`4qWbQG<2NRBQ#>6vbj{0#Lk$h>I&3U5U7G9IpA+m}oW{AUr}c(0s3 zO)k%IWrB3RR@}JTL({%1Nm_5Z_KmqBDTkt-?u#3kVn9GZ9F~v2e(sm00ZY&_0u^Elz(whu z_SIwE$z@W)H$f{?PM`dhZ(i5ubD29J&d=pV^L=~A;6-8)0EhZflT0qEX_dE>89Nrh z>z!)&*o%T#KXlqMz%raa^K3Nl9bnU5M5GKb2^thaK@i1?r_?Nt92H;`o+#O@KUmD1W;X8Ael?$lOXyV*5sD6tZf5XMG4**Vbs6gS52{yfJ9!O9cn@1%Mf4P0r3-q?VnGtTXJW zKu>zv-7t14nE%tjnX6n2akXF%A`@13z zG&z+qUMK+Q0Ad1BEXx2pKzja~hT3=$u-ILe{eEQK>ymMpwutA~B}Mst5<4EOw-r+J zAS>rEgi$2x6kq_&6ajld8dzEisPlqAt8NE%2?@#KXF+QVQ-l7;WuFhv!Dby7wLT6i z;E4)yk5+-*iANzBm5$~0IQZZ6Prgprfi$qeTX6Q^ng}J9 zgFYyzEo;FOXCikSRa+_A08QpXw^Kjt%PLM= zUH@*_bt~1;q|Z!;6j`Bp(!G+%dQ}mr9*%A#-t{eHzUHutAqVMt4TtpMZjsq=c`$4Iz7W{QnMV}G|AERlqp^lqiH!Cnap@?`ogim!g^zxkt zVA=^lH6HEBhatbC2x@&m0$hk;03K5<2C+`Ni?;~a2{)FX{@nBD#~JGu0_@PSQHB*? zhqYo07kLc@Q}Ph)UB9WR|G)&}dVH8bO$y>EjXpyr?dP9Q{>^v)YuIDS^Kb-xn8hLQy}fo~2#{n*$$Md`iH-Hh?gcpa_GlHUc| z6t)Omt;>nA$SGq2X0m`4bvHHj!8=uYz55sLB}H>1qLR*&Gu>O%-&Vmd@{h4O16rDx zL+KJ|H=2zC0H=JS3ziQa93~{!=Ss7|oN;qjBXsO0NC(NxfqCNvbU)*yJ}<43`tzTb zdz@@u$*VE|YJs08FU?u;;7w%OeDvFz)8__dJ>GPvOXAH6-q|S=0QJ%tIs(G)oE`|5 zMa#rvDz@@)*@7r1{)w;SRit@RwlzQ935snAGayBDXv<9Ev*`d2Y-QVHP05tl?$K8O zZp5Fg3L`dqM>tGpi~xIcWptE0F6x8DkT4to@J29Ix=k112hau-@!Jlu=_i!xc!aY*G>wS}-LzB;h%7n)N&&dGS+4;ef1CR6T zvpTS`uP?M&k2C>-gq$9^Yh2eztd9VND|!BLf%0c18Mv3uuz z3VwzfQyCh!mU75j|$HB43Ec=M#D|u;>Lm zTD{kJMaGzI!_jy@L#plf8bjr6p{TR>p>;O!6CK}@oUdY{HrJZgdx$v=LsN-!&{P*a zad0LwaF3ZdgJ7+p--8xsI>m(;1cD^)Y>@Z z>lQQEPx#QH&-Sl?%ZY$uJ|@34G}L?2K4qIjvtqmaaW?I3*9S|w>a5HInqe-NI>qnX z*4{eoX&L5;m}?*wJ0&$)IkSq|Ea3;rMH(EcWsN-*MmDW?MfU?guRk9F8a&2+TFQg) z#aFK%IL)?abOYdoir*M{Qsj=!D2E0sMTXEaTimi)Qmxl$E;$z%&hL~Ji&h2-44!|M z!BYmhd)HRIT9A(dT5d;5lmn*TNv9?c%0EIj%;t4x2+!<_KNP}LUtYqVH~#*>`B3H4 zIpLY#OW_|`Me*Y)C7Ce$r8*FsS~y;#4e*_}riWsVDh(L#UhXui&Pt_VE8B$D7K?D2 ziB~ph7!`D(qqvWKjGg)QmN_g)7GyS zc#dqU5;ctb?##C0kiS~7tDgE8ZMSsSX|qAv_>RJ}*a(g#SakcJ7;J@!7`WP2WfsB9 z_#aorY<{K1IUXB3JA<1(rsP$?ln49+L@c*6xJ#A78W=o~oi#ypLszcp84UYxe>~C&t~w=OSq~P^7OXre=C@ z>#q1rSIqULduF#7dbwpA^g-s&byH`_W|n^&2{^Hbp%Jo%L&KY`Jegd{nom%}kRQaWkiCSnKWM7~dCfGtX%AjiY-B znmUyQ_SM(2?S$RgXo|OeAx(j=Hnp5Ad$u zazW|qqu(ZTc|m~|9-@6tD9q^S3`J~E`o$!&`K?^@tzXB+>uo1q&-uL;NwH`G`bvI7 zfD#gg_mSrQn@P+5FY6|5(|u16x0zm%U3WqauS=SuoSEo0M|PL>uP1O-pYy1vu6(+y zn);C2>+Sx_Bz-Zt&JVcvy$2)*_qgBc(@r;s{A~0ex)jR&HmZe{&(t*dh$}HxT~wXg zkz(08VlbE-Kt#j`n8wn=j*ZD$`+>6WQ~Rf~=mC_2`Fj-_Co~RJB$yEx#9eQP6-{wP3(0De?Pg zM{BqE{8aML(3dE80hq?`utzin%Wp#wglAaxt0$`D=*+Kn2K&ddV3iTM;kHqOTi0G& zUNMqhR*BEtJl#`0%fiMohWF#bB(-W3q&sQe72(Xrhm7&a4I(1@gz5utNx>_e zJX60FR>O_Qilb=nspkwIqj;oqyN_w5o$q1?%KX7hXR*mG^y&j!-i9+xs>21JQ z`PR3=CVnMrEPkIJ>z)~=l3Dt-X=5^WmU%H^^|?1$Uzg5NhrPrb_?-y&D5!MVQj%8i z#JQZD)^f-zprsm(;`s2>#6Fz2(EhFqYAhq;ZQ9TSm~~L23K`ppO_575)L7O@wDLUa zG%`kQi(P-~*}0EhpTXw$m(!W;KUVlD#so^-z8jln$N27=9=;_I#6H`cI^(r8oEaWs zfG_%}VJ1Y6yQrP-5fdz2?n#}s$dXN<4Zd&EFHA?@2s>KqIFKAbUji)e*4qG!g3{W} zPlev4*QWFj-*9{CoPbjm5mZ9KSxp*KVuK7tS&a~Wcjk|xOA-%62_vnN<89Q;JTb0y zyKu{JnF<>%XjEj+h4+k%*#~>TP*bb z>>R>Jm8qlLE??i>mTFV?X(FOa2f5`P^;$i;aLrh=a_2P=&mgys|s5%%r@{k^Lweu^W#razO zeert^@DbvpMXL}xtGW^j=qckM7dWVRe&1L6vx_>{^aCblF*_J@ zDtC&*&zXPVd21!F_(G@{E2aQTW1S1slsq+SzC6!j*>`dj{NW0jB)t4y43o> zojLx?y$s-$h2~rmco1;4Q5rA*{y8<(ChRfJiI=eJ$XdBuPQy-72@Ex;vZlLAEb1~3 z&ksJFJkSD6q5pMspiKjzD=3pB6*BzS{m6g)1RgOz;MOLZY?zG``69uISTAl_&G&;O zE(sMD>m^-uoyI3OSrCVonShRB+Iid>t^N%XKwI=I0KuMui{Z3{TJp0=V0LdDDY!(u z7|8&}a(Nv>djcD3^a`PBc)eTy=I>#+I1`B_z~{j9J@;MtC(}kdGA~-ir5C3xGk>Z zz4+ymSD5^AJHU+^wXHwsxP2&{22M^NqU$d;*kRBJZPuOSs#aV}L~x3+C$(f+yNJlt?E)nqxUO=aDYG4W(aYDzCTve)?>DNG?&sF$WR3EBfeObJ~QUUbAn-Ul=nbl%TJR-Q}ofab)OVqUN9{S1uajLT$1R!d^IEIh)JL|@d_BnpN z8&yws0{DI&VFE~9(p#TK@5*+Uqgbn&lIow1t@rP(22X$BFvb1Yx`}rv|GS(+S50{-$kJU3RDU1ffl#-pM zEU$?9?phau%Xd#z#B8G)X|Xc5t7q(Oew${t_IU;tz{luYSIsU(Hivl`S-Dqt*nyGQ z{dyrPp-w9Axwm^pL&@J9#Wp=ip2jwtsy^D}LO1?+-R8LgRn0bR+mnzs z_&s9PN_yh`<7>ds58HaIcVZ?6RD5@7DEmw|XWpn`hB=FyirqWTDgfb;+mkbmkqp7!lP)%Q#HdWNX!-@?21 zwIhcG`m}S1!+y<}{|GbQ;5RMm9dZu9MFBGI9{e}i0Zp^xF}Kw~jNp{-PZ`4T!>@vM zHnZ50R?N#ju;g}4~{n2nE$7y|6A7pvD#{2 z3!ME<*pTo4d;>8R*aGA9{y!FA{;F9`j$#aC;PwXt^i}gqN}bcckGTQ*D*IhFzzD2p z-?Y@g0X6~o0WfcEcO72}^H2edueGlkI<-o38`UR#~8PU`k`6~i^7wC`+VD-fgT*Tr}b!a^0%HP?1R^M-DKVn-s zEZa}ixF2e+byDQ`SB5Rv-SB-`)A*k*BeXdaAcU=gJ}?fGn=U?pz0Ny*_o)xH<5eZR zYFH)pzj{`IwMvgez!6McZ3k}&eAsd<6!4v(Vm}M=J(0`QKC|FLV>N(zT;03c-TSEd zvR!l?Sj051n6gOa1%H7^Px=s8uCF~^3%FWa1vCKLpFP)PnyhBu-n6-@VCO9Sw{r&H zp)z^k9svF{FZJ&NS3*`%a6H8oAnR)YD*AGAYk&5nu?F-*F$dzP`t9p>_>OJK%~NdrG04hZv~Z&#=sf-EN;z`ISJW~Lft$e%9&T=XaCm?P&$^>h{ZD5T46 zAmI|w3&Eo}7#);vT6b+qu&9YlGux#6(=o95pj{nMU6%_2IvL?P(_Z!(HoQCaGvEqf z=dY4Iz=udA-gTr_eYO|Cke$@|xK_IgtjVrxXLz+g)OwI$7R6p|RShVM5;EsM_j1@Y z0_tCGL-!FDOnr!%fIJV02wDuYte=cv>(q_31xK|74SP*5NpxcdgXuy6j6%WYA zrBMUca8+F29DdSj_#}9`oR|vgXQ!SQ7870;)x&QphS4#Qeb_l)7wNy<87pdF6vx+m z3CbUfgf&(`rb~In0DVg;fT1fq1(Y{azQD}d2Jo#T#)E$+!?}mKo!anI{bBl^?eSc| zwM8d|hwbsK&)zDany?2J3NJnq|BCizq!8IQ#<2nV*xgp%cs@I{)H!q=fxUJGH|#$fEsxv;@%goxSD& zQ2ukaK}tEAt>PMkL%^X>gBReZiCf(%{DBwo{1rg2uRxN$IxZ&wtwgG&=wV8zl{htx zHm;%y;6|nQO&q8<00%iM5r7lI-in`}$NyFdoy{Z79sZp78C|^yfKz>kh`rHBkhJ^CBTl)ZG+eUm!|ei%dqJq!_^#g9!ap~j5U31H)eLy)|80H#fUS?O zwuQn!j{^*VZ=pJ|ph}$q`IKvQu~Q0KB5FD+cHkv4@HFlg1nJGMcObD|eWsd8?qkoi z9^TexdXzK87m+8j!d#fX`JNnu1k}A*7gI(1;E`stJV%xMIjWYP2@rGNa8=&L zhh%^XAmIh4`}kes_!C~GARD$HSOcEuc$2KQ479N31%<~a{@|{Y-s6WmbSM@OECAv* z#}5)yPa(1(;ZAY+rTp7}O2Pl$x3H21`T+H-KN(nbeu4#ZRFihFqovUu8jim4p#W@C z0J{6IMdArMI(_Rip62&C%%St#wj_fNzDs1nnOh;KA;EU|$4A_8nMXyIyw_KI*9KTV zcz1FjOCZvleb5(JT{Q5=MXBY;CP#gQNu;K1joPVKUM(LBV_c2rh%f5lqG zNB6XE_-z;UVBB>U`@RI72%u{*++jUBaOtK`#tPXp1iWb76MT>t)b$~&G1<`H3#fhl z{0`(Yo6ES_4HVCq-?bd$nHO^7GvYfzAJ-fDeeY_vo2NY{?QG$rq6`yHlV`(}UbOnI`=9rD4FWL<5SS_R$e=ufPv9w}(Ph z>{_U;7ogGo;nhh~(;;bCgB5xhtAiN+3!=1e9$Wx>mHH#sW2r~3nJIQ1B6u5sRI*D` z!20OJx4pHx>EiDKMM$cfpL%Km)X!Q>=zFm5ZCNSH{=NjbeXF3?8>QDMrn7J2k0uNQ zUI|57i3{PLP~#GxVYv<8-K|=Y-o+S>KH_Xvj9%oxR@apGlsySiO8`&V zt5y_LNrP%dA+U#_NIL}8tT)r*NZDq-yRw-~XdQM`@qL4jsxi|5)@@jO1~YhL=W*@y+IHN(*C;bU+uR}I39Z2N-S;mAXT+Ur0pFJC^>6#|PY7TFgqJ%+V*GgPzp0h-QaL$S+B>2s=pppycb9LO$3gbZBbO@3+3GIV6Yg$(S~) zQqZz2EhnmQsND@G&lZU%mZyzp%4VuW;p*l~uAclwjlTeRZ;_yps^r9%=naU&Xj z4F!q@4|WLMifl<_v&PS*FWmzE1ja$I7okG5T4~?$pj>zG0+l~s%8Z5_<8}`-DAT!C z`bnXM*gg2Cnk32rZA`amn##Xx5t<^X3%qN_)k#^g@*V5Bs2SD(%#i{Y(sC+8DbHfX zc`XI(4){!zY23?g$Y}qXwfXY+n!AtWGd@v|U9yhEb|{ z!zJT*)EAZX?n>VcR~5&_H4EFK4|zQk7%pAL9=v9VefKShMiiANncVD$$J=pG3J)iUr@78+5U!4(LvMxE-@%P{xc^jKo(R&Db(c$$^gXK3`&)|-AE(X6 zukyT{uYAE4;>DJA&wYaX@DF~#)lNb23?rtb_i>5Nx~sGEXIlp*tM0t!T+A@ZoPiFj z=qD;F$vgOu^dvf`HB(XJcJ*k*U)%~jK$Q$V=qLeBQBcwR8=Af6=f}pzc7Z>uSk3lA z7OOjT3TEb~c7BtMeC4X|@vn60FD)%C1J0Wo8x0sHwtCzPXCANb?d>J+J>?x*{t|I~ z?BO^5$=d;MUAVLHN3J9hqCN>8rXR@kE-G}URrVwjkNt7ou zkmq)CObBZm`4~IB{DiC>oSK>%B>`2pZ^vVA{c7L^v63&?3W=@B@7;f%4j>3gv6S zt{6voHT6_s*lnxg)60??zYk{5aP9CmD(tp|?g%~8tH0V_zjkeu2j2x1J}!%IcyBTW zE;aa?1~GX~_k4rh)K91UXV3H#yBXSx8y)ltH`mtI>RK1dE@qa$BpvQ(zF=6K!8kZR zDITi9pG7;H)EsNmvqY`G@=IJi67^1$Nj%a#pLwDxBg1<1c$bQb$^!=nr}s_RZbQ;l zH5!jo>1b12mSgq{qoz5|yBg!2TkK@|rA^mA^;oYTAJ1?dBx%YhB%%Iv8Dj_~Pd{>kdFsbaXk z^T39che_JX?V7O?HM%7R+h`O5rZ+&zYNIN@>$EIRXHJ8-8CB$>EvSMEF-m0#p zy}jMJr1khm5Y@4jeKJ^R7#`xXC<~QQMu8VM>A;g{LR^+;!f~lPNatBkg*v7@7{wW+bIwSzsUyS*8Q zxu>bIt+ko6u?OpO7YF-WK2UdaXBQwADg=c?*`Vh3rVeJ-_LjhghN z$aDU@jRk~>-ejbCxBO>h2>fKZ$wQNGd`wnAJiXd~{{2{qJCE?($%nA4`zddWy-(zfPqD|VLxk(+fyFGR zJRehJa;`dL8g3nf!Ky^Pnjwx{1n@WajW@~F$#2Our?LD^f{fmryZ2=m!s2OE^_1zH zZI+A@GLZmM0`FDx?4iCG%;h?0(U9x#!x%D7@HaA&D`49VdCl*a-TbR19(m5&T*z=) zf;=^ycoen!BPFruNx;o@?sjJXFE4xgfhx|9P|+_u$WTG>Ka6+e_$&i?Z5EaSzv|i) zh(AC^z+}69km1M-!A<1$>dN=7mBqeo4P-ht-NZ!XZPc&$n8ezpCbcLcT!WAac@n*y z7$XoS9KT*6oadr~gRO2pEu5dFd<@}wLc^5(Crj%MQi92JgyAc5WHSEK7Ya8gj~N&c z&~rW~cb43bnX^kuqfJ+K0S+*~o9yrjH55i@=>0yw`g&1b@r~cozcMy03i(Ol+y>Q8 z232k(-^kk2WfAVZywF63!T#_+%k*(Bev;Qei!5z$W8MIVnhv&2e;3BF4B=}|oo@&E zHvJbbL$lKm&>KyV)kd7lDiRuUF)YQ& zKUyZjRo@W|guxK@t0AlfH`4f0B9V9U#6^VWBcn|a&SF_92x#={`PVtuPVWqR1gVh` z@CXFLxyb5oHf~-NuR)j`bDXR;*H`2%Hx*WdLW?4ApWN|!^Z2bb=FC>m6FJxGcjmaPWpvB6?}_4@aPO7kH+<-2&jqwJhIHf zO$VI=0=9kLMa=z_0;6H@34|+W`wqhXl`;Y&$v28HR-v6z zq0602*}f5g{BPkW@cch6O`p8{{mJ76I|!NY%Z^(J~vLo6ZnVud$>DNE420AXR0!}II? zl<1e|L#Au4TnotC%)Bpaz4mun0~C6fzrXtMRQGwVm)q!TVV5Pf9H*N*Qnwv40#_=d zMf2VuTy>CP{0yh2uW7+knE6>-zT4yeAbfs!A>+9a6ZF?Vh zQ`2E369uwt$Ut~C@?bIW-9RzWA}n&w9ohE4VD8n79xodo7psjTZ@8({rdrH35{sGU zW(<*44t+BErZjYK(yS7M7CCcNL^vI@%R0FIy4z2-mEUoQ%qj>No4l zH?;v~Tm!o~<2pX$<(+7Z)MR?H9Qz&o5g0rX0llV2Kwo>M)4zNrb6z;s^J$d9xi3y4 z{mF+h_`0LoGx?PK3pQ$>g~7*NTrxD_rbZmd`U8Wdd_(4wznh-}DT^mmor4D%#QP`Z zecs5zO~=9OO*_}ks`+c~=8_9xa?rkbEoPW}{3NLNqT1~E0w$f! z4GwxpIX9KzrY}JzhMA00Ngw>FOvQukVMo@)Mxl*y(1#aFu9cel|9S?0S6H)-LjXLrup#Q`;O+A84&aeA|k=31&KNn}Ljn{p~BcUJJNUyQ`Q41>gJ(7rTFvWZeSYF||HjDl!dU^o>Bx z_eyb9#y3S#fc@rSj2$f+LbVfHZVC>tx`8lJlp04SGgm^GEaw`_wM$2+34T2HfNRsl zB&$spo^soaTm2nkNW5i7ri8&3r#A);r`_, + **endpoints** are the start and end node of a path. + An endpoint can be an end host, but it applies slightly more generically to any node which is + the source or destination of SCION traffic, e.g. to a gateway. + + The terms "endpoint" and "end host" are used mostly interchangably. + End host is preferred where the focus is (physical or virtual) machines and the software + running on them, and endpoint is used otherwise. + + ISD + Isolation Domain + + An Isolation Domain (ISD) is a set of participating :term:`ASes `. + ISDs can overlap, i.e. ASes can participate in multiple ISDs. + + An ISD represents a scope for Certificate Authorities (CAs) in the :term:`Control-Plane PKI`; + CAs can issue certificates exclusively to ASes in their ISD. + + At the same time Isolation Domains also serve as a local routing domain. + Inside an isolation domain, links between ASes form a directed acyclic graph, allowing + efficient path discovery. + Only the core ASes (i.e. the ASes at the top(s) of this directed acyclic graph) need to + participate in the less efficient inter-ISD path discovery. + + SCMP + SCION Control Message Protocol + + The SCION analog to `ICMP `_. + + A supporting protocol for the SCION dataplane. It is used by SCION routers or end hosts to + send error messages and for diagnostics (ping and traceroute). + + See :doc:`/protocols/scmp` for more information. diff --git a/doc/hidden-paths.rst b/doc/hidden-paths.rst index e8a5dd0aa..4a24fd1aa 100644 --- a/doc/hidden-paths.rst +++ b/doc/hidden-paths.rst @@ -2,7 +2,12 @@ Hidden Paths ************ -This file documents the design for the hidden paths infrastructure. +.. admonition:: TODO + + Add the EPIC-HP overview documentation (from the design document). + + Move configuration file description to the Manual section. + Overview ======== diff --git a/doc/index.rst b/doc/index.rst index a5e77cf52..ce12baffa 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,54 +1,120 @@ -Welcome to the SCION project documentation! -=========================================== +SCION: a next-generation inter-domain routing architecture +========================================================== -If you would like to contribute to SCION project, the :ref:`contribution-guide` -is a good place to start. +SCION (Scalability, Control, and Isolation On Next-generation networks) is a +secure and reliable inter-domain routing protocol, designed to provide route +control, failure isolation, and explicit trust information for end-to-end +communication. -.. toctree:: - :maxdepth: 2 - :caption: Developer docs: +.. (Comment) + This documentation is structured into sections with different purposes/audiences - contribute - build/setup - build/dependencies - testing/index + - Technology: + Explanations and Specifications. Explain SCION on a conceptual level. + Should introduce concepts that a user or dev needs to make sense of the manuals etc. -.. toctree:: - :maxdepth: 1 - :caption: Design docs: + Target audience: anyone (users, developers, outsiders) + + - Reference manuals: + Target audience: users of **this** SCION implementation (operator of SCION + infrastructure or hosts), users of any of the SCION APIs. + + - Developer section: + Target audience: contributors to **this** SCION implementation - cryptography/index - protocols/index - PathPolicy - hidden-paths - beacon-metadata +Technology +^^^^^^^^^^ + +The ideas and concepts behind SCION. .. toctree:: :maxdepth: 1 - :caption: Proposals: + :caption: SCION + :hidden: + + Overview + Control Plane + Data Plane + Cryptography + sig + glossary + +* **Overview**: + :doc:`SCION ` | + :doc:`Control Plane ` | + :doc:`Data Plane ` | + SCION End Hosts + - uri - grpc - EPIC - ColibriService - BeaconService - PathService - endhost-bootstrap +Reference Manuals +^^^^^^^^^^^^^^^^^ + +User documentation for the services, tools and programming libraries of the `open-source SCION +implementation `_. .. toctree:: :maxdepth: 1 - :caption: Operational manuals: + :caption: Reference Manuals + :hidden: - manuals/common - manuals/router - manuals/dispatcher - manuals/daemon manuals/control + manuals/router manuals/gateway + manuals/daemon + manuals/dispatcher + manuals/common + + command/scion/scion + command/scion-pki/scion-pki + + snet API + +* **For operators of SCION end hosts**: + :doc:`command/scion/scion` | + :doc:`manuals/daemon` | + :doc:`manuals/dispatcher` + +* **For operators of** :term:`SCION ASes `: + :doc:`manuals/control` | + :doc:`manuals/router` | + :doc:`manuals/gateway` | + :doc:`manuals/common` | + :doc:`command/scion-pki/scion-pki` + +* **For developers of SCION applications**: + `snet API `_ + +.. TODO + snet documentation should be a good starting point for using SCION as an application library. + For this, the package documentation needs to be streamlined a bit... + +Developer Documentation +^^^^^^^^^^^^^^^^^^^^^^^ .. toctree:: :maxdepth: 1 - :caption: CLI tools: + :caption: Developer Documentation + :hidden: - command/scion/scion - command/scion-pki/scion-pki + dev/contribute + dev/setup + dev/run + dev/style/index + dev/testing/index + dev/dependencies + dev/design/index + +Start with the :doc:`dev/contribute` to contribute to the open-source SCION implementation. + +* **Policies and Processes**: + :ref:`governance` | + :ref:`change-proposal-process` | + :doc:`dev/style/index` + +* **Building and Running**: + :doc:`dev/setup` | + :doc:`dev/run` | + :doc:`dev/dependencies` | + :doc:`dev/testing/index` + +* :doc:`dev/design/index` diff --git a/doc/manuals/common.rst b/doc/manuals/common.rst index 828437dec..859ea7e56 100644 --- a/doc/manuals/common.rst +++ b/doc/manuals/common.rst @@ -1,7 +1,332 @@ -*************** -Common settings -*************** +************* +Configuration +************* +The general pattern for the long-running SCION services (:doc:`router`, :doc:`control`, +:doc:`gateway`, :doc:`daemon`), is to load a :ref:`.toml ` configuration file +which is specified with a ``--config`` option when starting the service. +This configuration file specifies all options for running the service, in particular the +**configuration directory** from which all other configuration files are read. + +The set of required configuration files differs between the applications. The configuration files +are organized specifically to allow sharing the configuration directory between different services. + +.. _common-conf-toml: + +Configuration .toml +=================== + +This configuration is a `TOML `_-file. + +The following options are implemented by all applications. + +.. program:: common-conf-toml + +.. object:: log + + .. option:: log.console.level = "debug"|"info"|"error" (Default: "info") + + Log level at startup. + + The log level can be changed at runtime via the :ref:`HTTP API `. + + .. option:: log.console.format = "human"|"json" (Default: "human") + + Encode the log either in a human oriented form or json. + + .. option:: log.console.disable_caller = + + If ``true``, disable annotating logs with the calling function's file name and line number. + By default, all logs are annotated. + + +.. object:: metrics + + .. option:: metrics.prometheus = + + Address on which to export the :ref:`common HTTP API `, in the form + ``host:port``, ``ip:port`` or ``:port``. + The eponymous prometheus metrics can be found under ``/metrics``, but other endpoints + are always exposed as well. + + If not set, the HTTP API is not enabled. + +.. _common-conf-toml-db: + +Database Connections +-------------------- + +The services use different SQLite database files, with paths and advanced connection options +configured individually. +The pattern is: + +.. object:: some_db + + .. option:: some_db.connection = + + File path or `SQLite URI `_ for SQLite database. + + .. option:: some_db.max_open_conns = (Default: 1) + + Sets sets the maximum number of open connections to the database. + + This **should** be left at 1 for SQLite databases. + + .. option:: some_db.max_idle_conns = (Default: 2) + + Sets the maximum number of connections in the idle connection pool. + If this value is higher than :option:`max_open_conns `, + then the effective value is the same as :option:`max_open_conns `. + + This **should** be left > 0 for SQLite databases, in particular + if an `in-memory database `_ is used. + +.. _common-conf-topo: + +topology.json +============= + +The ``topology.json`` file of an AS specifies all the inter-AS connections to neighboring ASes, and +defines the underlay IP/UDP addresses of services and routers running in this AS. +The topology information is needed by :doc:`router` and :doc:`control` instances, and also by +end-host applications (including the :doc:`gateway`) which usually obtain it indirectly from the +:doc:`daemon` running on the same host. + +.. Note:: + + The topology.json configuration file contains information that is not relevant for all consumers + of the file. + + For the sake of simplicity, you can use the same topology.json file on all SCION components + within the SCION AS. In more advanced configurations, an extract of the topology.json file can be + presented to each specific component. + +The structure of the configuration is presented as a pseudo-JSON with a more detailed explanation +of the individual fields below. + +.. + Comment: use YAML syntax highlighting for JSON because this allows annotation comments and + accidentally gives pretty nice coloring for placeholders. + +.. code-block:: yaml + :caption: Pseudo-JSON description of the structure of the ``topology.json`` configuration file. + :name: topology-json-structure + + { + "isd_as": , + "attributes" = [<"core">?] + "mtu": , + "border_routers": { + : { + "internal_addr": , + "interfaces": { + # ... interfaces definitions ... (see below) + } + } + # ... + }, + "control_service": { + : { + "addr": + } + # ... + }, + "discovery_service": { + : { + "addr": + } + # ... + }, + } + +.. code-block:: yaml + :caption: Each ``interfaces`` entry defines one inter-domain link to a neighboring AS. + :name: topology-json-interface-entry + + : { + "isd_as": , + "link_to": <"parent"|"child"|"peer"|"core">, + "mtu": , + "underlay": { + "public": , + "bind": , + "remote": , + }, + "bfd": { # optional + "disable": , + "detect_mult": , + "desired_min_tx_interval": , + "required_min_rx_interval": + } + } + +.. program:: topology-json + +.. option:: isd_as = , required + + The ISD-AS of this AS. + +.. option:: attributes = [<"core">?], default [] + + Role of this AS. ``["core"]`` for core-ASes, ``[]`` for non-core ASes. + + .. Note:: + + Historical relict; there used to be multiple different attributes ("core", "issuing", + "authoritative", "voting") which could apply a more fine granular role configuration. This + functionality has moved into different places, only "core" remains. + +.. option:: mtu = , required + + Common Maximum Transmission Unit in bytes for SCION packets (SCION headers and payload) + for intra-AS connections. + This is the minimum MTU between any two internally connected border router interfaces. + +.. object:: border_routers + + .. option:: + + Identifier for a border router instance. + Matches the :option:`general.id ` of a router instance. + + .. option:: internal_addr = , required + + UDP address on which the router receives SCION packets from + sibling routers and end hosts in this AS. + + .. object:: interfaces + + .. object:: + + An interface ID is the AS-local identifier for an inter-domain link. + + The interface ID is an arbitrary number between 1 and 65535, + assigned without external coordination by the operator of the AS. + + In this ``topology.json`` file, the ID is contained in a string. + + .. option:: isd_as = , required + + The ISD-AS of the neighboring AS. + + .. option:: link_to = "parent"|"child"|"peer"|"core", required + + Type of the link relation to the neighbor AS. + See :ref:`overview-link-types`. + + .. warning:: + + Link type ``peer`` is not fully implemented yet. See :issue:`4093`. + + .. option:: mtu = , required + + Maximum Transmission Unit in bytes for SCION packets (SCION headers and payload) on this + link. + + + .. object:: underlay, required for "self" + + Underlay specifies the local addresses used for the underlay IP/UDP connection to the + neighbor router. + These addresses are only relevant to the router that operates this link, i.e. the router + instance with :option:`general.id ` matching + :option:` >`. + + + The :option:`underlay.public ` is the address of this side of the link, + while :option:`underlay.remote ` is the address of the remote side of the link. + + In the configuration for the corresponding interface in the neighbor AS, these + addresses are exactly swapped. + + .. option:: public = , required + + The IP/UDP address of this router interface. + + .. option:: bind = , optional + + IP address to which the router should :manpage:`bind(2)`. + + This can optionally override the the IP in :option:`public `, + for the case that router instance is running in a container, a VM, or generally any kind + of NAT. + If NAT occurs, :option:`public ` is the address of + the interface as seen by the neighbor router, while bind is the local address. + + .. option:: remote = , required + + The IP/UDP address of the corresponding router interface in the neighbor AS. + + .. option:: bfd, optional + + :term:`Bidirectional Forwarding Detection (BFD) ` is used to determine + the liveness of the link by sending BFD control messages at regular intervals. + + These settings are only relevant to the router that operates this link, i.e. the router + instance with :option:`general.id ` matching + :option:` >`. + + .. option:: disable = , default false + + Disable BFD, unconditionally consider the connection alive. + + Takes precedence over :envvar:`SCION_EXPERIMENTAL_BFD_DISABLE`. + + .. option:: detect_mult = , default 3 + + After ``detect_mult`` consecutively missing control packets, the BFD session is + considered "down" and is reset. + + Takes precedence over :envvar:`SCION_EXPERIMENTAL_BFD_DETECT_MULT`. + + .. option:: desired_min_tx_interval = , default 200ms + + Defines the frequency at which this router should send BFD control messages for this + inter-domain link. + The effective interval is the result of negotiating with the remote router during + session establishment; + the value will be ``max(desired_min_tx_interval, remote.required_min_rx_interval)``. + + Takes precedence over :envvar:`SCION_EXPERIMENTAL_BFD_DESIRED_MIN_TX`. + + .. option:: required_min_rx_interval = , default 200ms + + Defines an upper bound for the frequency at which this router wants to receive BFD + control messages for this inter-domain link. + The effective interval at which the remote router will send control messages is the + result of negotiating with the remote router during session establishment; + the value will be ``max(remote.desired_min_tx_interval, required_min_rx_interval)``. + + Takes precedence over :envvar:`SCION_EXPERIMENTAL_BFD_REQUIRED_MIN_RX`. + +.. option:: control_service + + .. option:: + + Identifier for a control service instance. + + .. option:: addr = , required + + The address of the control service. This is *both* a UDP and TCP address; + + * The UDP address is the underlay address for the control service's anycast address. + This is used when communicating with control services in other SCION ASes, using SCION. + * The TCP address is used to serve the grpc API to end hosts in the local AS. + +.. option:: discovery_service + + .. option:: + + Identifier for a discovery service instance. + + .. Hint:: + + The implementation of the discovery service is part of the control service. + This usually points to a control service instance. + + .. option:: addr = , required + + See ``control_service.addr``, above. .. _common-http-api: HTTP API diff --git a/doc/manuals/control/metrics.rst b/doc/manuals/control/metrics.rst index ec8490e41..7f2cb7b5f 100644 --- a/doc/manuals/control/metrics.rst +++ b/doc/manuals/control/metrics.rst @@ -4,10 +4,10 @@ The list of control service metrics is incomplete. Renewal -^^^^^^^ +------- Renewal requests ----------------- +^^^^^^^^^^^^^^^^ **Name**: ``renewal_received_requests_total`` @@ -19,7 +19,7 @@ control services with CA functionality enabled. **Labels**: ``result``. Renewal requests per handler type ---------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Name**: ``renewal_handled_requests_total`` @@ -38,7 +38,7 @@ Renewal requests per handler type parsed and delegated to a handler. Renewal request registered handlers ------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Name**: ``renewal_registered_handlers`` @@ -50,7 +50,7 @@ registered. **Labels**: ``type``. TRC local filesystem writes ---------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Name**: ``trustengine_trc_file_writes_total`` diff --git a/doc/manuals/router.rst b/doc/manuals/router.rst index 8782d2804..7bebbc39f 100644 --- a/doc/manuals/router.rst +++ b/doc/manuals/router.rst @@ -2,6 +2,153 @@ Router ****** +:program:`router` is the SCION router. Due to the encapsulation of SCION packets, +this can use ordinary UDP sockets for network communication and so can run +on almost any host system without requiring any special privileges. + +.. TODO + add reference to dataplane section + +Command Line Reference +====================== + +.. program:: router + +.. option:: --config + + Specifes the :ref:`configuration file ` and starts the router. + +.. option:: help, -h, --help [subcommand] + + Display help text for subcommand. + +.. option:: version + + Display version information. + +.. option:: sample [file] + + Display sample files. + + .. option:: config + + Display a configuration file sample. + +.. option:: completion [shell] + + Generate the autocompletion script for :program:`router` for the specified shell. + + Run :option:`router help completion ` for a list of the available shells. + + Run :option:`router help completion [shell] ` for usage information on the + autocomplete script for a particular shell. + +Environment Variables +--------------------- + +.. envvar:: SCION_EXPERIMENTAL_BFD_DISABLE + + Disable :term:`BFD`, unconditionally consider the connection alive. + + Applies to BFD sessions to all sibling routers (other routers in the same AS). + Can be overridden for specific inter-AS BFD sessions with :option:`bfd.disable ` + in an interface entry in the ``topology.json`` configuration. + +.. envvar:: SCION_EXPERIMENTAL_BFD_DETECT_MULT + + Set the :term:`BFD` detection time multiplier. + + Default 3 + + Same applicability as above; can be overridden for specific inter-AS BFD sessions with + :option:`bfd.detect_mult `. + +.. envvar:: SCION_EXPERIMENTAL_BFD_DESIRED_MIN_TX + + Defines the frequence at which this router should send :term:`BFD` control messages. + + Default 200ms + + Same applicability as above; can be overridden for specific inter-AS BFD sessions with + :option:`bfd.desired_min_tx_interval `. + +.. envvar:: SCION_EXPERIMENTAL_BFD_REQUIRED_MIN_RX + + Defines an frequence at which this router should send :term:`BFD` control messages. + + Default 200ms + + Same applicability as above; can be overridden for specific inter-AS BFD sessions with + :option:`bfd.required_min_rx_interval `. + +Configuration +============= + +The :program:`router` is configured by two main files. +First, the :ref:`.toml ` configures common features like logging and metrics and +specifies the **configuration directory** from which all other configuration files are read. +The second one is :ref:`topology.json `, which contains all the AS information +that the router uses to forward packets. + +.. _router-conf-toml: + +Router Configuration +-------------------- + +In addition to the :ref:`common .toml configuration options `, the router +considers the following options. + +.. program:: router-conf-toml + +.. object:: general + + .. option:: general.id = (Required) + + Identifier for this router. + + This is used to identify which parts of the :ref:`router-conf-topo` file refer to self. + Thus, ``id`` must match a key in the :ref:`router-conf-topo` files' ``border_routers`` section. + + .. option:: general.config_dir = (Required) + + Path to a directory for loading AS :ref:`topology.json ` and :ref:`keys + `. + + If this is a relative path, it is interpreted as relative to the current working directory of the + program (i.e. **not** relative to the location of this .toml configuration file). + +.. _router-conf-topo: + +topology.json +------------- + +The :program:`router` reads the ``border_routers`` section of the :ref:`topology.json ` file. + +It uses the entry referring to its own :option:`general.id ` +to determine the intra-AS links that this router instance is responsible for. +The other router entries ("sibling routers") define which router is responsible for which +interface. This mapping is consulted during packet forwarding to determine the +sibling router to which a packet transitting the AS needs to forwarded to. + +Additionally, the :program:`router` considers the ``control_service`` and ``discovery_service`` +entries. These entries define the underlay addresses that the router uses to resolves +anycast or multicast service addresses. + +.. _router-conf-keys: + +Keys +---- + +The :program:`router` loads the forwarding secret keys ``master0.key``/``master1.key`` from :option:`/keys `. + +The key files contain a base64-encoded high-entropy random string. +The keys should be exactly 16 bytes long (corresponding to a base64 encoding of 24 bytes with two trailing pad bytes ``==``). + +.. note:: + The :program:`router` and :doc:`control` currently use these keys as input for PBKDF2 to generate + the actual forwarding key. Consequently, keys of any size can currently be used. This may be changed + to only accept high-entropy 16 byte keys directly in the future. + Port table ========== diff --git a/doc/manuals/router/http-api.rst b/doc/manuals/router/http-api.rst index da31e9914..ebcc0bfe1 100644 --- a/doc/manuals/router/http-api.rst +++ b/doc/manuals/router/http-api.rst @@ -1,8 +1,8 @@ -The HTTP API is exposed by the ``posix-router`` and the ``router`` control-plane application. -The IP address and port of the HTTP API is taken from the ``metrics.prometheus`` configuration +The HTTP API is exposed by the :program:`router` application. +The IP address and port of the HTTP API is taken from the :option:`metrics.prometheus ` configuration setting. The HTTP API does not support user authentication or HTTPS. Applications will want to firewall this port or bind to a loopback address. -The ``router`` and ``posix-router`` currently only support the :ref:`common HTTP API `. +The :program:`router` currently only supports the :ref:`common HTTP API `. diff --git a/doc/manuals/router/metrics.rst b/doc/manuals/router/metrics.rst index d6aa6f0cc..af0491607 100644 --- a/doc/manuals/router/metrics.rst +++ b/doc/manuals/router/metrics.rst @@ -105,10 +105,6 @@ router in a different AS. **Labels**: ``interface``, ``isd_as`` and ``neighbor_isd_as``. -.. note:: - - Not currently supported by the ``router``. - BFD packets sent/received (intra-AS) ------------------------------------ @@ -121,10 +117,6 @@ router in the local AS. **Labels**: ``sibling`` and ``isd_as``. -.. note:: - - Not currently supported by the ``router``. - Service instance count ---------------------- diff --git a/doc/overview.rst b/doc/overview.rst new file mode 100644 index 000000000..f17a60446 --- /dev/null +++ b/doc/overview.rst @@ -0,0 +1,111 @@ +************** +SCION Overview +************** + +Scope and Goals +=============== + +SCION is an inter-domain routing protocol, designed to provide route control, failure isolation, and +explicit trust information for end-to-end communication. + +SCION's main goal is to offer highly available and efficient inter-domain packet delivery, even in +the presence of actively malicious entities. + +SCION's aspiration is to improve *inter*-AS routing and to focuses on providing end-to-end +connectivity. However, SCION does not solve *intra*-AS routing issues, nor does it provide +end-to-end payload encryption, and identity authentication. These topics, which are equally +important for the Internet to perform well, lie outside the scope of SCION. + +Concepts +======== + +Isolation Domains (ISDs) +^^^^^^^^^^^^^^^^^^^^^^^^ + +SCION organizes existing :term:`ASes ` into groups of independent routing planes, called +**Isolation Domains (ISD)**. +An AS can be a member of multiple ISDs. +All ASes in an ISD agree on a set of trust roots, called the **Trust Root Configuration (TRC)**. +The ISD is governed by a set of **core ASes**, which provide connectivity to other ISDs and manage +the trust roots. +Typically, a few distinguished ASes within an ISD form the ISD’s core. +Isolation domains serve the following purposes: + +- They allow SCION to support trust heterogeneity, as each ISD can independently define its roots of + trust; +- They provide transparency for trust relationships; +- They isolate the routing process within an ISD from external influences such as attacks and + misconfigurations; and +- They improve the scalability of the routing protocol by separating it into a process within and + one between ISDs. + +ISDs provide natural isolation of routing failures and misconfigurations, provide meaningful and +enforceable trust, enable :term:`endpoints ` to optionally restrict traffic forwarding to +trusted parts of the Internet infrastructure only, and enable scalable routing updates with high +path-freshness. + +ISD and AS Numbering +^^^^^^^^^^^^^^^^^^^^ + +SCION decouples :term:`endpoint` addressing from inter-domain routing. +Routing is based on the ISD-AS tuple, agnostic of endpoint addressing. + +ISD numbers are 16-bit identifiers. +The 48-bit AS numbers are globally unique, and use a superset of the existing BGP AS numbering +scheme. +Formatting rules and and allocations are is currently described in `wiki page "ISD and AS numbering" `_. + +The endpoint local address is not used for inter-domain routing or forwarding, does not need to be +globally unique, and can thus be an IPv4, IPv6, or MAC address, for example. +A SCION endpoint address is the ``ISD-AS,local address`` 3-tuple. + +.. _overview-link-types: + +Link Types +^^^^^^^^^^ + +There are three types of links between ASes in SCION: + +- A **core link** can only exist between two core ASes. +- A **parent-child link** requires that both ASes are in the same ISD and + that at least one of the two connected ASes is a non-core AS. + ASes with a parent-child link usually belong to the same entity or have a provider-customer + relationship. + Every non-core AS needs at least one parent link. +- A **peering link** also includes at least one non-core AS. The ASes may be in different ISDs. + Peering links are only available for use by children (direct or indirect) of the two linked ASes. + +Routing +^^^^^^^ + +SCION operates on two routing levels: intra-ISD and inter-ISD. Both levels use **path-segment +construction beacons (PCBs)** to explore network paths. A PCB is initiated by a core AS and then +disseminated either within an ISD (to explore intra-ISD paths) or among core ASes (to explore core +paths across different ISDs). The PCBs accumulate cryptographically protected path and forwarding +information on the AS-level, and store this information in the form of **hop fields (HFs)**. +Endpoints use information from these hop fields to create end-to-end forwarding paths for data +packets, which carry this information in their packet headers. +This concept is called **packet-carried forwarding state**. The concept also supports multi-path +communication among :term:`endpoints `. + +The process of creating an end-to-end forwarding path consists of the following steps: + +1. First, an AS discovers paths to other ASes, during the *path exploration* (or beaconing) phase. +2. The AS then selects a few PCBs according to defined policies, transforms the selected PCBs into + path segments, and registers these segments with its path infrastructure, thus making them + available to other ASes. This happens during the *path registration* phase. +3. During the *path resolution* phase, the actual creation of an end-to-end forwarding path to the + destination takes place. For this, an endpoint performs (a) a *path lookup* step, to obtain path + segments, and (b) a *path combination* step, to combine the forwarding path from the segments. + +.. figure:: fig/overview-routing.excalidraw.png + + +.. seealso:: + + :doc:`control-plane` + Overview of SCION's path exploration process. + + :doc:`data-plane` + Description of SCION packet header formats and processing rules for packet forwarding based + the packed-carried forwarding state. diff --git a/doc/protocols/assigned-protocol-numbers.rst b/doc/protocols/assigned-protocol-numbers.rst index e0fbf4cdf..c990da0ff 100644 --- a/doc/protocols/assigned-protocol-numbers.rst +++ b/doc/protocols/assigned-protocol-numbers.rst @@ -9,7 +9,7 @@ This document lists the assigned SCION protocol numbers. Considerations ============== -SCION attempts to take the `IANA’s assigned internet protocol numbers +SCION attempts to take the `IANA’s assigned Internet protocol numbers `_ into consideration. Widely used protocols will have the same protocol number. SCION specific protocol numbers start at ``200`` which makes them very unlikely to clash. diff --git a/doc/protocols/bfd.rst b/doc/protocols/bfd.rst index 3f8d6e816..c7b850b70 100644 --- a/doc/protocols/bfd.rst +++ b/doc/protocols/bfd.rst @@ -5,9 +5,8 @@ BFD on top of SCION .. _bfd-specification: BFD (Bidirectional Forwarding Detection) is a network protocol that is used to -detect faults between two forwarding engines connected by a link. (See `rfc5880 -`__ and `rfc5881 -`__.) +detect faults between two forwarding engines connected by a link. +See :rfc:`5880` and :rfc:`5881`. BFD can be layered on top of different transport protocols. This document describes how BFD should be layered on top of SCION. diff --git a/doc/protocols/index.rst b/doc/protocols/index.rst deleted file mode 100644 index 7e583d567..000000000 --- a/doc/protocols/index.rst +++ /dev/null @@ -1,16 +0,0 @@ -=============== -SCION Protocols -=============== - -This page contains SCION control and data plane protocols and specifications. - -.. toctree:: - :maxdepth: 2 - - assigned-protocol-numbers - scion-header - extension-header - scmp - authenticator-option - sig - bfd diff --git a/doc/protocols/scion-header.rst b/doc/protocols/scion-header.rst index ed7bee297..3ad6f7400 100644 --- a/doc/protocols/scion-header.rst +++ b/doc/protocols/scion-header.rst @@ -559,9 +559,7 @@ entities should be able to access the services, downgrade to the SCION path type should be prevented, etc.), ASes need to be able to configure the border routers such that only certain Path Types are allowed. This is further described in the accompanying -`EPIC design document`_. - -.. _`EPIC design document`: ../EPIC.html +:doc:`EPIC-HP design document `. Packet identifier (PktID) ------------------------- @@ -744,4 +742,4 @@ verifies the LHVF field. Again, if the verification fails, the packet is dropped. How to only allow EPIC-HP traffic on a hidden path (and not SCION -path type packets) is described in the `EPIC design document`_. +path type packets) is described in the :doc:`EPIC-HP design document `. diff --git a/doc/protocols/sig.rst b/doc/sig.rst similarity index 87% rename from doc/protocols/sig.rst rename to doc/sig.rst index 87bf21ae8..ab6bf49d1 100644 --- a/doc/protocols/sig.rst +++ b/doc/sig.rst @@ -1,12 +1,21 @@ -*********************************************** -SCION IP Gateway Framing Protocol Specification -*********************************************** +**************** +SCION-IP Gateway +**************** -This document contains the specification for the SCION IP Gateway (SIG) -Framing Protocol. +The SCION-IP Gateway (SIG) tunnels IP packets over the SCION Internet. -Introduction -============ +An ingress SIG encapsulates IP packets in a SCION packet and sends it to an egress SIG determined +by the configured routing rules, where the packet is decapsulated and forwarded toward its +destination IP address. +From the perspective of IP, a SIG looks like a router. +From the perspective of SCION, a SIG is a regular application. + +.. admonition:: TODO + + SIG Overview and introduction + +SIG Framing Protocol +==================== SIG Framing Protocol describes frames sent between two SIG instances. The IP packets transported via SIG are encapsulated in SIG frames. @@ -26,7 +35,7 @@ Each SIG frame has a sequence number. The remote SIG uses the sequence number to reassemble the contained IP packets. The Stack -========= +--------- SIG framing protocol on top of SCION and UDP:: @@ -41,7 +50,7 @@ SIG framing protocol on top of SCION and UDP:: +-----------------------+ SIG Frame Header -================ +---------------- Each SIG frame starts with SIG frame header with the following format:: @@ -78,7 +87,7 @@ All fields within SIG frame header are in network byte order. multiple frames. SIG frame payload -================= +----------------- SIG frame payload may contain multiple IPv4 or IPv6 packets, or parts thereof. No other types of packets can be encapsulated. The packets are @@ -91,7 +100,7 @@ of an IPv4 packet must be at least 20 bytes long. Initial fragment of an IPv6 packet must be at least 40 bytes long. Example -======= +------- Following example shows three IP packets packed into three SIG frames:: diff --git a/doc/testing/index.rst b/doc/testing/index.rst deleted file mode 100644 index 871f16b22..000000000 --- a/doc/testing/index.rst +++ /dev/null @@ -1,14 +0,0 @@ -======= -Testing -======= - -Testing documentation: - -.. toctree:: - :maxdepth: 2 - - buildkite - crypto - hiddenpaths - mocks - goldenfiles From 055822f1b11a18460fba183a571f66b22c79827f Mon Sep 17 00:00:00 2001 From: Steffen Date: Wed, 31 May 2023 08:33:32 +0200 Subject: [PATCH 025/255] docFixing two links in README.md (#4345) * Setup link * Contribution link --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6a8fbd44b..e98ad5d61 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,13 @@ packages](https://docs.scionlab.org/content/install/). ## Building To find out how to work with SCION, please visit our [documentation -site](https://docs.scion.org/en/latest/contribute.html#setting-up-the-development-environment) +site](https://docs.scion.org/en/latest/dev/setup.html) for instructions on how to install build dependencies, build and run SCION. ## Contributing Interested in contribution to the SCION project? Please visit our -[contribution guide](https://docs.scion.org/en/latest/contribute.html) +[contribution guide](https://docs.scion.org/en/latest/dev/contribute.html) for more information about how you can do so. Join us on our [slack workspace](https://scionproto.slack.com) with this invite link: From 8d65af280cfea9e4c2f5f5a99f8c9523ea57367a Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 1 Jun 2023 15:17:27 +0200 Subject: [PATCH 026/255] doc: consistent naming of the Traffic Class field (#4347) The Traffic Class field used to be abbreviated by QoS, an unnecessary alias. Traffic Class is also the name used for the equivalent field in the IPv6 header. Also, fix the documented NextHdr value for the SCMP protocol. --- doc/protocols/authenticator-option.rst | 6 +++--- doc/protocols/scion-header.rst | 4 ++-- doc/protocols/scmp.rst | 2 +- pkg/spao/mac_test.go | 8 ++++---- tools/wireshark/scion.lua | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/doc/protocols/authenticator-option.rst b/doc/protocols/authenticator-option.rst index a8714862a..b7af39fc0 100644 --- a/doc/protocols/authenticator-option.rst +++ b/doc/protocols/authenticator-option.rst @@ -222,13 +222,13 @@ The input for the MAC is the concatenation of the following items: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |Version| QoS w\o ECN | FlowID | + |Version| TC w\o ECN | FlowID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | PathType |DT |DL |ST |SL | RSV | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - QoS w\\o ECN - The QoS field from the Common Header, but with the ECN bit set to 0. + TC w\\o ECN + The TrafficClass field from the Common Header, but with the ECN bit set to 0. 3. The :ref:`SCION Address Header ` diff --git a/doc/protocols/scion-header.rst b/doc/protocols/scion-header.rst index 3ad6f7400..81a7ada87 100644 --- a/doc/protocols/scion-header.rst +++ b/doc/protocols/scion-header.rst @@ -21,7 +21,7 @@ The Common Header has the following format:: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |Version| QoS | FlowID | + |Version| TrafficClass | FlowID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | NextHdr | HdrLen | PayloadLen | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -30,7 +30,7 @@ The Common Header has the following format:: Version The version of the SCION Header. Currently, only 0 is supported. -QoS +TrafficClass 8-bit traffic class field. The value of the Traffic Class bits in a received packet or fragment might be different from the value sent by the packet's source. The current use of the Traffic Class field for Differentiated diff --git a/doc/protocols/scmp.rst b/doc/protocols/scmp.rst index 99b85325f..84b0d8295 100644 --- a/doc/protocols/scmp.rst +++ b/doc/protocols/scmp.rst @@ -24,7 +24,7 @@ General Format ============== Every SCMP message is preceded by a SCION header, and zero or more SCION -extension headers. The SCMP header is identified by a ``NextHdr`` value of ``1`` +extension headers. The SCMP header is identified by a ``NextHdr`` value of ``202`` in the immediately preceding header. The messages have the following general format:: diff --git a/pkg/spao/mac_test.go b/pkg/spao/mac_test.go index 2d6a7e8f0..d9ad62fc2 100644 --- a/pkg/spao/mac_test.go +++ b/pkg/spao/mac_test.go @@ -135,7 +135,7 @@ func TestComputeAuthMac(t *testing.T) { 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number // 2. SCION Common Header - 0x3, 0xf0, 0x12, 0x34, // Version | QoS | FlowID + 0x3, 0xf0, 0x12, 0x34, // Version | TrafficClass | FlowID 0x0, 0x0, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV // 3. SCION Address Header 0xa, 0x1, 0x1, 0xb, @@ -170,7 +170,7 @@ func TestComputeAuthMac(t *testing.T) { 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number // 2. SCION Common Header - 0x3, 0xf0, 0x12, 0x34, // Version | QoS | FlowID + 0x3, 0xf0, 0x12, 0x34, // Version | TrafficClass | FlowID 0x1, 0x43, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV // 3. SCION Address Header 0x20, 0x01, 0xca, 0xfe, @@ -246,7 +246,7 @@ func TestComputeAuthMac(t *testing.T) { 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number // 2. SCION Common Header - 0x3, 0xf0, 0x12, 0x34, // Version | QoS | FlowID + 0x3, 0xf0, 0x12, 0x34, // Version | TrafficClass | FlowID 0x2, 0x0, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV // 3. SCION Address Header 0xc0, 0x0, 0x0, 0x2, @@ -302,7 +302,7 @@ func TestComputeAuthMac(t *testing.T) { 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number // 2. SCION Common Header - 0x3, 0xf0, 0x12, 0x34, // Version | QoS | FlowID + 0x3, 0xf0, 0x12, 0x34, // Version | TrafficClass | FlowID 0x3, 0x0, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV // 3. SCION Address Header 0xc0, 0x0, 0x0, 0x2, diff --git a/tools/wireshark/scion.lua b/tools/wireshark/scion.lua index 81f90dea0..c6503cc72 100644 --- a/tools/wireshark/scion.lua +++ b/tools/wireshark/scion.lua @@ -45,7 +45,7 @@ local HOP_EXP_UNIT = HOP_MAX_TTL / 256 --local scion_raw = ProtoField.bytes("scion.raw", "Raw packet") local scion_version = ProtoField.uint32("scion.version", "Version", base.DEC, nil, 0xf0000000) -local scion_qos = ProtoField.uint32("scion.qos", "QoS", base.HEX, nil, 0x0ff00000) +local scion_traffic_class = ProtoField.uint32("scion.traffic_class", "Traffic Class", base.HEX, nil, 0x0ff00000) local scion_flow_id = ProtoField.uint32("scion.flow_id", "FlowID", base.HEX, nil, 0x000fffff) local scion_next_hdr = ProtoField.uint8("scion.next_hdr", "Next Header", base.DEC, hdrTypes) local scion_hdr_len = ProtoField.uint8("scion.hdr_len", "Header Length", base.DEC) @@ -79,7 +79,7 @@ scion_proto.fields = { scion_raw, scion_version, - scion_qos, + scion_traffic_class, scion_flow_id, scion_next_hdr, scion_hdr_len, @@ -148,7 +148,7 @@ function scion_proto.dissector(tvbuf, pktinfo, root) end tree:add(scion_version, tvbuf(0, 4)) - tree:add(scion_qos, tvbuf(0, 4)) + tree:add(scion_traffic_class, tvbuf(0, 4)) tree:add(scion_flow_id, tvbuf(0, 4)) scion["next_hdr"] = tvbuf(4, 1) @@ -787,7 +787,7 @@ function epic_path_dissect(tvbuf, pktinfo, root) -- Get the timestamp of the first InfoField -- (No checks needed, as SCION path type parsing was successful) local tsInfo = tvbuf(24, 4):uint() - + -- Calculate and add the EPIC timestamp (absolute) -- (depends on the timestamp of the first InfoField) packetTsTree:add(epath_ts_abs, tvbuf(0, 4), NSTime.new(tsInfo+epicTsRelSec, epicTsRelNs)) From 5ba8660e4dbca784b4fef9516d455b7e1add58df Mon Sep 17 00:00:00 2001 From: rohrerj <26304001+rohrerj@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:22:37 +0200 Subject: [PATCH 027/255] doc: design document for border router performance optimizations (#4339) --- doc/dev/design/BorderRouter.rst | 264 ++++++++++++++++++ .../design/fig/border_router/br_design.png | Bin 0 -> 54681 bytes doc/dev/design/index.rst | 1 + 3 files changed, 265 insertions(+) create mode 100644 doc/dev/design/BorderRouter.rst create mode 100644 doc/dev/design/fig/border_router/br_design.png diff --git a/doc/dev/design/BorderRouter.rst b/doc/dev/design/BorderRouter.rst new file mode 100644 index 000000000..80e54f411 --- /dev/null +++ b/doc/dev/design/BorderRouter.rst @@ -0,0 +1,264 @@ +********************************************** +Border Router Performance Optimized Redesign +********************************************** + +- Author: Justin Rohrer +- Last Updated: 2023-05-25 +- Discussion at: `#4334 `_ + +Abstract +=========== + +Right now, the performance of the border router is very much limited because a single goroutine per +border router interface is responsible for reading, parsing, processing and forwarding the packets. + +Background +=========== + +The current border router design was not created with performance in mind. +Previously, there also existed a design which did something similar than the proposed design in +this document. +`See `_. +Redesigning the current router pipeline is expected to lead to significant performance improvements. + +Proposal +======== + +The pipeline gets changed to have seperate goroutines for the receiving, processing and forwarding steps. +This will lead to a much higher performance because the expensive processing logic is moved to other +goroutines and to improve the performance we can just increase the number of processing routines. +By introducing packet reuse we do not have to allocate memory at runtime to store the packets because we +have preallocated memory. + +Design +-------- + +The border router will consist of three layers, the receiving, the processing and the forwarding layer. +The communication between those layers are implemented as go channels. + +Receivers +^^^^^^^^^^^ + +There is one receiver per border router interface that is responsible for batch-reading +the packets from the network socket, identifying the source and flowID and using them to identify which +processing routine has to process the packet. +Then the receiver enqueues the packet to that processing routine. +If the queue of that processing routine is full, the packet will be dropped. +All receivers share a pool of preallocated packet buffers that they can use to store the packets they +receive. +This can be implemented as a go channel of packets where the receiver reads a certain amount of packets, +updates the pointers of the ipv4.Message.Buffers to the buffer inside those packets and then performs +a batch read. + +Processing Routines +^^^^^^^^^^^^^^^^^^^^^ + +There are several processing routines and slow-path processing routines +in the border router that are responsible for processing the received packet. +The actual processing logic remains unchanged. +If the processing routine identifies a packet that belongs to the slow-path, the processing routines +enqueues the packet to a slow-path processing routine. If the queue of the slow-path processing routine +is full, the packet will not be processed at all. In this case the buffer is immediately returned to +the receivers. +Once a packet is processed, it gets enqueued to the forwarder which is responsible for the egress +interface. +If the queue of the forwarder is full, the packet will be dropped and the buffer returned to the +receivers. + +Forwarders +^^^^^^^^^^^ + +There exists one forwarder per border router interface that is responsible for +forwarding the packets over the network that it receives from the processing routines. It collects +packets from the go channel up to the point where either no further packet is available or the batch +size is reached. +Then it forwards the packets as a batch. +Afterwards it returns the buffers back to the receivers. + +.. image:: fig/border_router/br_design.png + +Mapping of processing routines +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To prevent any packet reordering on the fast-path, we map the flowID together with the full address-header, see +`SCION header documentation `_ +to a fixed processing routine using the fnv-1a hash function together with a random value which is generated +on startup to prevent pre-computations of the exact mapping. +To mitigate the sticky-zero property of the fnv-1a hash function when hashing, we take the random value first +and the flowID and address-header afterwards. + +Initial parsing in the receiver +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To minimize the time that the receivers need to parse the fields needed to map a packet to a worker +we will use a custom parse function that just parses the fields that are needed for the mapping. +The values of those fields will be the same as if they would have been parsed with the slayers.SCION +parse function. + + +Slow path +^^^^^^^^^^^ + +During processing, packets that have to follow the slow path are identified and forwarded to the +slow-path processing routines. +To do so, we hand over the current buffer to the slow-path routine together with the error codes. +Because of that the slow-path processing routine might have to redo some of the parsing if necessary. +The original processing routine can immediately continue processing its other packets once it forwarded the +slow-path packet to the slow-path routine without the need of doing anything additional compared to the usual +packet processing. +Rate limiting of slow-path operations is not implemented explicitly, but only implictily through +specifying the number of slow-path processing routines in the configuration. +In case a packet is identified to belong to the slow path but the queue of the slow path is full, the +packet is dropped. +Packets currently identified for slow-path are: + +- Malformed packets + +- SCMP traceroute packets + +Processor queue size +^^^^^^^^^^^^^^^^^^^^^^ + +The processor queue size will be automatically determined as follows: + +.. code-block:: text + + processorQueueSize := max(ceil(numReaders * readBatch / numProcessors), readBatch) + +Pool size +^^^^^^^^^^^ + +The pool size will be set by calculating the maximum number of packets in-flight through the system: + +.. code-block:: text + + pool_size := numReaders * readBatch + numProcessors * (processorQueueSize + 1) + numWriters * (writerQueueSize + writeBatchSize) + +Configuration +--------------- + +The configuration of the border router will remain in the border router toml file. +The following configuration entries are added: + +Number of processing routines (N) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By configuring the number of processing routines one can specify the number of goroutines that are able +to process packets in parallel. +Unlike the other settings, the number of the processing routines are directly taken from the +environment variable GOMAXPROCS. + +Number of slow-path processing routines (M) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By configuring the number of slow-path processing routines one can specify the number of goroutines that +process the packets on the slow-path. +An optimal value could be a percentage of the number of processing routines or even a fixed number. +A default value would be 1. + +Read-write batch size +^^^^^^^^^^^^^^^^^^^^^^^^ + +By configuring the batch size one can specify how many packets are read or written +from / to a network socket. +A default value for both batch sizes would be 256. + +UDP read-write buffer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This setting allows to configure the UDP read and write buffer of the sockets. +The actual applied values are subject to the system rmem_max. +A default value would be 1MB. + +Considerations for future work +-------------------------------- + +Multiple receivers per border router interface +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +We could deploy multiple packet receivers per border router interface and use eBPF to make sure that +all packets that belong to the same flow are received by the same receiver. +Because the rest remains unchanged we would still have the "no-reordering" guarantee and significantly +increase the read speed. + +Lock goroutines to threads +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The CPU affinity by locking the goroutines to threads and CPU cores can later be studied. + +Replace go channels with custom ring buffer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the future we might want to replace the go channels that are used for communicating between the +goroutines with custom ring buffers in case this provides higher performance. + +Traffic control (scheduling) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With the implementation as described in this document the forwarders process the packets from one +single queue. +In the future we can use additional queues for prioritized traffic between the processing routines and +the forwarders. +See `PR 4054 `_. + +UDP generic segment offloading (GSO) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the future we could add UDP generic segment offloading (GSO) for the connections between border router +of different ASes to improve the performance even more. +Such an implementation would be feasible in the future because we would just have to identify +which border router interfaces are affected and for them make some changes to the IO parts. + +UDP generic receive offload (GRO) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the future we could add UDP generic receive offload (GSO) which seems to better perform than just +recvmmsg and would therefore improve the performance even more. +Such an implementation would be feasible in the future because we would just have to identify +which border router interfaces are affected and for them make some changes to the IO parts. + +References +^^^^^^^^^^^^ + +`GSO / GRO `_ + +Rationale +========== + +One packet pool per receiver vs one packet pool for all +--------------------------------------------------------- + +There was the option to use a packet pool per receiver or a larger one for all receivers. +The advantage of using a single packet pool for all receivers are that we don't have to keep track to which +receiver the buffer has to be returned and that the total amount of memory we have to allocate would be smaller. + +Packet pool as channel vs stack +--------------------------------- + +If we implement the packet pool as a channel we can make use of the fast and optimized implementation by go +but if the channel size is too large, the packets might not reside in the cache anymore. +On the other hand if we use a stack we would not have the problem that problem but now all goroutines that +try to read or write to the buffer pool are now fighting over the lock. +Both solutions have advantages and disadvantages but I would suggest to implement it as a queue because +go already provides a good implement for that and if we later realize that the other solution would lead to +better performance, we could still change it. + +Compatibility +=============== + +This is not a breaking change, just a performance improvement. +All other components will be able to interacet with the border router the same way as before. + +Implementation +================ + +The implementation as suggested in the design document can be implemented in seperate pullrequest to +make them easier to review. +All those changes below should lead to a border router following this design document. + +- Restructure the router/dataplane.go file to have a reading, processing and forwarding functionality together with buffer reuse support + +- Add slow-path support + +- Add configurability for the new functionalities + diff --git a/doc/dev/design/fig/border_router/br_design.png b/doc/dev/design/fig/border_router/br_design.png new file mode 100644 index 0000000000000000000000000000000000000000..e462b62addb26cc4d383c014a77d01b0f77f9fdf GIT binary patch literal 54681 zcmeEv1zc2F`#&NoqoTm5U=Ty9NOz}zlA@H9#1IlgcM1xEq|&KkQi4jCNQ0nAh?D{X zlF|+TbBCD~V|RVu{cZUEcRz~EoqJC_=ZWw0J2r=%s6aB#LF zaBy%f@VA32_aX__aBwtX_+b~%mZNVk*y*bLj#Lxt3uyGF?3mZEl3kM?`&pB33T6R%(R`7#^m5G;~_x#5F zx<*I~OoMVLXA?6sU0OCtP9_%6)KOIv3j>sc4fs|59QeV?0xq+Qf#1LvTpSy}I%0pZ zwg*kKvhXso90PYqA@xmBpe5)j@P`##k~FbK8loJ*MOIcer~_!YNLyW_jiGXxvf8qm zv8pRct4P>6vam@TOCUGyu}50ln4l~$Gh$_8W#ZoW!q&+WxpCD1X>X#BzMcIfEsH2< z82ZC5j*$=eV4-V{xmOWPnGp;K>fQt+Cp}I*ZarN+Hb#A3BpV}}z99!Aj~<&YBO8aI z0jn;XE|&ot`iaf0WBV|7l(N>fG?qgdAk9FN296s;V&!1R%+bJU;|ezq=o0GH$Qs)( zW*E?gvnI}%0kUGAGqN)=K-yqh!^{|kGP5<#20r!7tZSIntgj!)x^Noc;j9kHjMP4yQPsPM#k8lS-E&OMyaQ(Z)#+X zva`VSXMwW7ETy?Fwi(PEZH#q+ify!vzVxkxv2wOXp+HZYmUrWe%|9VK5l5Oq%YchVItkvzl^qVD2&Aq@q}h)Wuka(JxIygZ>d60ry~3?6-&i9Zht!J}oV6$H``Y zMpD%7^trPt&PHb$SvfEQ+r0kJU^dAgX<;A=nKO{EzL~C#jfwu3BL8xIenr}#MU)-Ocyb=0}F`c_4}?6A;oi zX$$*?OfcHQ$;Qrv(HCrA8=}EH_hYKC(cN!!`jv`)t$Mb))<#I%KhPym30=r0uye44 zW({IB+wb_f%>)1S;bVu3kr@~E^Y7cpf7L$wf7d>{I2g}{Abvze(6?`LD8Ky-=5BO6 z`Mo>82|M34uni0WyyO3wu_GN#Y}J5Y0LY97^1je#b;uJlv9R!9K1)De6Y|{9mlDu| zVm~M%txbSy1)hK7+ON8f4P^y){hI6G#2D27nCswV<7VRGL+7KYtBLDBb3MU&c)0fVSjhBOohhx(iFkfTG@L#)`zuQ(gfg6TA@fWtjWd;zS zn1P8sz(hvSuUO!+@da=Oo4y10e0{q$($>z}0zeteS6@Hyb>IboP*ztD!1^yBj;@)B z5tNPS15^mvju?b?OaN{c#e89IVqgG)CoyZJjfu0a9vVnNMu+jyz>YY@XgMXom0vZv z?;t1)&d0O|ojW#yPp1_B8G=UVqQHmf+8Co#8YpURN?)Msin_MIt|1Et{+@*$++bsC zjWR`IlVE_b#C{NS|BuB(9^NleEgSYT)<^u`hdf>^8-fkGUw8TQMmUUr{lc4lCjyQ}T;QTU#d#y`*bri~3UIe>DRAZoY^G zeZP+mF~I1LTf+}$j8NSBeZ~je^M9JnVUjZZEJa-C$ z8-@_^0+1*6DLv?UG#0{M`5jR6rRVw~Hs>4a<~sz>AAliTJR3TQweSsG!^X0SMPS8V z+sx)*`3kJ_`3C?L%uK#m|G(a(0WP(6!ls2#{6b$)2kw9oB#JCxBVgmo=gbg#;B#sS zefr_t@b}#W#`=HXOa{lrq zv;_ib0#;dn-mryP&P_V5gw#g@8V`6P$S-}R@Besz0~T;&&_AEQ;R3RT#Jy=PzL7s< zO@A_k_ze~cOG6t&{pma$HfP%8;kel` zzGE|@V&%rTLTr@!`ymwDE^d*QR2`!f+0)_?uJ zqr-3`|MQLxE0IlFB8jqg(8VNLKOrjN!UD!kHv5xgL0sR`wDL$>2b8txH{j$S4-Q$e zWdxg+;k&LAtAYO@&-pDe`qM507cVA#`U#ie+kEL8Gx*OcJT|5GY+q#eXt0eAJil!D z{+VHj8xxv0hoRr9ar)y?Xw&LrYe+W37wokkW(ogL`p<>+a~R%=la1}quPgbb5ChXG zJ9f@kzw=-73Rs%sPpvEYdicM5{(ZJ~V|<%`LN!)jQ8K@@hZPSN(Eexb|73L~*qz!< z=;x2Rn14uJ33mDZ$6N>ZZ`PHt^78)0btT;2sVias->fUaZZ>>jE8j2>|JIfKP!%EM zfxoRQ`PvC{u(JQN>q@Y7>tE=^U(YdY`0Vd&w*4;iiFK2kk=S=D5Vd z9_AA(kuR3?TQmPZ*og&+$ws@sPjr5zQvbN*mkaA0G3ben6~iBI!rea!2f>ZW7r$8l zujCII!JoY|@|iYd2gL!KXhZZ)>@P&(U&9;ziuD6(A6<+N_J@HB`mW#LL@UCNq)T6g zgdcVjKhicfMfnEy1N^e#Jh8B!2lM$4XGMQ^87y|mHtF%E-Byf}+x(%kI^PL6-xQzz z$m)Ex@(=|97UdhC!u#|3ly3>O4XxWG|G(C!uz(YVn|#XOuoZ#jfc`>2@gutU8=m6J zVxwP(#h>3(e7jM$c?;wxbQR!e#fE+Tgz)3fBz>W1_l4E-^8Vrm{u&^`^Zz&V3yS11 zTU;2t@t07);2=H5923-?woDUXt-!#|r;?`WFo7+jE8gqx>)T_e!+CC5A9B zMA-NOxQ~C&6#`rQ=Fj(2zHj{SKb`>Q#^j`%vh2Sjv)kzNJNfwU62Mqb`MX38_7yaL z+@=07vjeHkUw;$_E0Hgj^jkasKOlfXRnz|p0Sticm+A3O%m9P;A^an1<3BUNEIeOS z>--&OasCGL|3h>QgiJP;5u5Y;&oH~#rP$=4HZi+DL8;`o&H}quo6z=8vR%aUFSYy4 ztEsRg&tC`?{;03`GI;&(aJ$&0*yJlVbGtvIv-mm4U44U-28=SYQhH7XqM|I~l17&H z7r*n$zO!a12S!Wi-G)DKgi7w4)Z!mk2*Annr6qA-%PBT__Ft}TCQ`738+JG4FFil> z-NpKLSL7SBb#1-rLFONWoj(wZ8FHZe%RFh0+Yc8_n!r4 zadLcRGT2N8tG|DO$#8rbkGQa}zruF;4>B3F5&p`%im?Xz`F+uw5ij~%>>H~$zQ8;H zy#;)uAUDGQWCIQkCC(`c(Q}U4qw%|%$&{T+xE;zD4g>Y|39H2}3F-l}p%bxA^96}L?(_8%qtU#}fdU1*T=*h5xP+cK zc$7F>pkEn@-t2`p5u3z#{c;KVmJK(Ga62ycCiML;k8hEcPRTXdz4>v%QXiJ>n5H&b z^-_V^zV#W+>2XghyUV({H`_pwjQI<8-9DeJAEk$HS-t$ZN8g=v&{G2+!LAB!H=+1E-XwiI7DQA?5P?(vuFnk+#zMm)cG=w|^jW4NRrt^h$PQ20l6-D} zk_#FZ%^Yd6+h^f<1rb3r;N$B5$h4^eGxV@VS*4dZ$%Tv>nt`oZ^=qw74ZJ}Q>y3WM z+$Op3NkTLD_$K6D!KMcOS%L-2#5-9Z#roX5GuP_L;7Dtljm=<#9W^zze$&wco&Cu| za}kUhoi~o1edzO!6g}gkr=V#a<30C=0LWE@9k0Kfy5sFr)2=vPo2+$aQ>NN+Rob(% z()%wS*$UPu=@42G-d4Xq3O&9bwh$hYrje81Rp2nsiRezP-s5gpwr&BsACJ-xvbq;< zAES|FaP_*{*?aP2U8u#W4;HISvlboM=ISf1Cs6K%AEP)-!a9oGTnzmUI4g5Fou&+O zOxx059bvGKe2zAj3w|SGs|i}f6fSZCx^b&<>SbDYO`#lH?{Gci}(3m)3Ki(PL)k?dZs+rfssP>2waFs?4 zwpA1!uJ*1OYI+>@qi;f^gOGI*$f|x-u>;K7ag)_OY^{eV4_yL=@Nx@os?YBC^?WSk zLsUSmyx!pz!lHSsdWVKDbK{-7{r)-;HDbGdnGfuCW00STTCSyTwi4oQU-ET%>zr<9 zQ^O+$9w^Ew1{&fF(z*;+M>thu$_0^2d$%3}GvSj*>y{(zCD7v}bKGv9>S@ZXm`tZ> z!yMyRw~Fd7rz-Btahe{;`}q3a#4JuhIWZhTCsFUmO|jNflz<5BNHy42Sv8Cl<1&BC z@d>e*o%f0y8srVM)f@{nTEg9ePf8iWjc`YbbxVF=UYTY%QZc?y?y}C7$wm*qXCZ?U zEB?}x>Y;252))xPY3DheQzEw{C*y-PFFgXSd3k3NtuFY$<#h`-St;iHfkJ8~NA^Qv zOUR(KL0w60o3Q72B4cQHIKg4A-2DtH*NUA?U$P@A!b4WXKP_@Qw%?VXgI3KJZJoA( z(pkWZhS4i>Aewa5Umfkn4fnVm?%}98H(NsTyjPXaA60m~SOb}wqd&`zSlrQjo#gT! z$oCjWqrKKt$Zg(DCYz4-TKU>rXEys6B--Zd#DfMlx!wE?VLKDN^w`uu1lmI~?&Xc~ z-sJZ9(Aqx2DYCxF6P!o8y(a?w#(O@yqNEYD(@1Z_S>5C}{~auj*IzB!8CHZA1?grz zz`;epu3ft}3U@Ct^2nP&i5rTJ9>ptOe1XbWaP5VUvnMXf-k3AlhZ_UybnFYXXnCkS ze&w*m%Q(6`Q7GDpP~g`0&0X0}SDs)P&UTlFLANg{h;U&lvSd^xUGrnI{2R1-m6C56 zuyTpf6&p2CIi~Obn3!wNFus>uELR>wMqv|h$(huGcVi(NXrd|=uuxEt^%Hz?94Tw1 zQdTKShWHeo;aZ{PzW70Y*az~(IC!H(7szw&9sH`>VbzjhrlJ`odb_gi=%_h|&l246 zdN*88;qmE%XXC;jSt&~4uPm3W7ZiLd+tnq<-PIgQ{#p)Fb`x}q^k233wyk&o#D#(1 zo=7aJxINyX+i846XWd!KS(Y0ziR6=>PMrw}QG_lr%C%9wsXl?;d}8k+G%T!SBAM)z z=*^&cP+kbena&k_!Gf6MNV&mUp$PzANCf<4YL4BX(opK-2{T7OE*XK~{ z1LRKqp~V$>HiPo>9~C@e0#ZdO7hSUOx>p9c3p!9GU0PNZ`_VCJFwQ1Oqr}~9&NJWD zCEwNReQfv4U4vzXDrgba=vj=(BPXO|d2Q~_TF}J`)6uA##2-Evr)fZYLP+bdv`Dwl zY(!3B1)1~E&GARi_t@+e_~g0#f!QN^b=e0lZ`qN9q9FAqLn{O&P>4y#(OBby@Fu*I zcUX_g-zf`;IE4H9o&tp%bt}U6NLbe`yZ%tA{E>{3?s(U!nu}93L};fpBnRX=UR~<* zrX~H{z&@j6vZKvsaHlAjM%y2EdG8hCIelTOzh<1jXHj12>PvIznQTZ6nivup>B`gX z@37tDk8^kTZi@v&V;yBFlaw}OiA`S5dwa5FwjLaAzbfl&dsd5JicWW4P-Qw zd+*nckPA;oH|FLP&!&;lh(tn~@rDl4ap5m@+_J+wCy%{R;I-RwN6)x)@JBi*N+!7brx@B0? zd*^$AtC{J1I*7`YrTVMEU2H--O5W`BF{f~QK1Iui$3d9XzhXw`!aF)=m z%53epGw%gEcvkcn2(#U02{^LCncylG>yc_z%?r54KAKV z;u8Mus8587;4W24vC@4Tcj27~&b*%1S2%Z1KO| zYj)dHJe$bcn&Hsp#p%HU2vz}<-8Qatmd>C(3u#dkMtgg)K92Wwm)m?7gs8)9%6-mB zR(XMdwG9NU`o8^Fv+8XGKA(IoV{o0X;>fi9>B>bZKtJ$f^=$z_R}k<1s#hC$>Lpdb=6q( zSQe-XJj{JD_hElqxiS6&6nv3rD=y)E1xkZ>_F(qlHnN*hArZ3D?Yl^svWEA3T;~_+ z@9)rzaHhW8-)2f{Fg@_%cFOL)s$hr5Mve9dd)Duv{M&i}t%R!e6vnQsWsY!`4$_TJuzvd@9wd=qM zOE{fuwQRN8@)G=ZIkS+*D`t7tNcTn`$7w~)u}}0=HCC;u>UU(NGxpNe4z&4HB4*90 zg!O>iorU?NPG?&1Q+FV$7%A)-Q>*W52LZb=Xf<@ic%7tVM9x_p*J*VD!?ko>#?GFJOWh#|5A#q? zA7!Y#&{r9FyD_*w5f-YE+|Q_5Ot2Vhw%C#HPc`EV)`HJq8dWtMdAmPMSlgmP^ReLz z?ZzkI<_BRqaBsTgV!3{)-5?1P@(QsNYCY{&?_J-gpJ+6k5&$!~r2B+)-(Yt}dLQUn z@m#y*(9%)+{Dlz5HTS;Wj!gfaw)gYlIfgaaAZL0t0jsH+G~d1C^Dq)NnL?3O&$PF` zu9ZP*v50$iYCWrj8_}IqJyApi^}F@Ue!EAa2?wmWmwIn}G3UG-u$~(oS1&2HzYn6l zTucU!8@CU`u}jDvZJqrP9U{``lPoxDKGWcARe5*!j|3E*m#Q zF{NX&!cqM)SLa6CudhB{AlqZN!=$ATbk*X{ZKo;gZr&^vyE@%-n9ZV-M^^gm)*C#8 zo~0tV<_$JQVW*HxRX)3qTnx7_^`S8ndmH0w*bo;@AhgJ#UQFiv{0hNwrYCQQJ?_-9 zTPn)BFTx{}V)*PXX6t2|yuN!aZoN#T=1lfVMbWxeH{mke&o%mHs(U~8B2_v6MB!^j zt$f>=wu+WeSJ`!1?<|{)Z2zWO|GIRof;d-pJ_f}0?Lx=IC=s}m(R3BHjC|^~pgQC0lS`h4vp;+pE!;CwvDHG&i?JXXDKUKK=UG2WS%9*GDQTFT_nE%PxeSxLLp?I;_^^GYt74Y}`B z$%6ZiMVDf&^<~jMa=4OVbLL*ae9(ABO*;z1^{klYf&JDzB_*t(&MvmAI!-4M3d_`t zS_~) zq7HkYamhJ2m^V+E6S0egX>?IQDZ_W?>S@2DAv&}NpAh%TNta|V9rK61;%}|ljr)KY zYLON3c3^6S*8pU7w?UKS+)$GqvVN@aTWKsvoGDr9F1BVT*ZP_?e;ASfqB4(1Q^??T ze@SX#i`AYLdX2S~B6mAx;o@m#?V+}a)YO@`EC{|TUUgAQB(x|G=_L9zwO1%p9J}DA zyDM6AEJ|1rS7iMv%WlN=-x_y^jXDVNj$ z-EydKk`UHU>J$*}LE1Ig`{Cofed>z%L=+*?JKC1=%#rWA=cRYYj+X`QVA#OY^1Je{!?@It|5x!KqL za`j#i=@bWN4_*w~K(P`wZY{MhoUK}iUAOLdp0UNxUpy&8&q|sAmw+g#;V|w4j%#*q ztcWPWJ9m_Y8AmGA6Ge*fKc!SDEWa8`(LzjlgW%Qd{g%(yGVlds)5mM*ILt$@&v zW2c>Xa{zy18XRq^X`QJgMrjS)mMklWJn!@1Ege7L+f4bAaLaHZBINY*jegIZKR^3A zOFM2B)*OIS;=J;NBCz=Fekx)7W_pqMHlzEzmo}#HVpf@f8%!f*n&8OplI@ho_jnci zS0Fg?IV3#!Q25DBEF1mah)`L50{V5souw+xAQv8!x}EW__z3?S@!<<+KY?9iS--=` zQZym}a_Jdg&ks(8({wbe@7u@7&oebxFtoW(u%?Z%-#ZDVz;Yl(M1>hHsKs+3-cJr+ z^y+QCv!i{8O2lob$=eLd$#=_mI=QOpSLOF}fa!VN` zoLx~rAYGQxll5aPx`>pqYAvgJb`_o^L`)Jj4mhY9IADTkS?S6nw4Y|( z;W2&R_pThKNO5(S>^#Vy`=PWvj1;aXlX1RXDembfE6ZNI`@!YgxSEPGJXS}>2Vzn7 z8E#{yT_f7_`EFV1%MR3}(s0~xkaw$=9T=mOmFAck?&&Jb$ zS?Jiy`neIf%z5_8o>R+jA>EP}RWQ>e({++WtN#F#=1?IlZ=pA!D+^iIDJ3)&Iw}@I zfNM^Czo3bAXn|{4OoI>~kRJjZ?;lOFB6Jre1LdtGD-`-_VFC;9yvK)b2ixzUaDBu- zl;qtB5}(1!z{7*&ZZl`*fv3%LnJ8)_b6muq5F;DqmxjVDxq6j;d0;2^hq95hj zrV-%=kTBb)sH9mdF}TCeTDPhj@v0N)ZqUA6cu`e$BkU^nQG^9=!)xPuPh7ql&v#m+ zzG`8z?{UlC5;E&*#CU?sxbFVs+xnL*0E_Y~yi4_AI~7qr0m30Zz<)&m#gO~Rg5a_{ zeB9LE=BVaqCo8Vg?S|vhRprork_a*A*SywmGYzwcnDDlH4Q*uZ$$$fsC!}}G-m3!~ zm>Wbza+LeLd7Y|MxzC8!>_{^au3qzpWs&}t)RS-gM|ljot$)*P@j}wY+}@1l zxL`BL#37_xG^r1C`I-VJVsKJEmJsBdvWX(IWe zNFyt4wgopw!3}S_tRwzW5RVuL5f^rDI8@vSsm_-G%`gf2{t&nYcfAm{1=NdiS-G!> zD+n^K1Y(95>czlKA`nn7x653zt$qklgI&{Y_?<$tM5HY55lNl^c8mCU9>c(HHF7I) z0P}KZ0POz%y3d|uIX^#kSnM#zzDXs3cKR zPIK}dr@}TK*>0a}%C463VaJKefL(4XIjz;7e$i*7gi|L@M=#7wiZDA z1ySly2eX1KJ_90VBt^wS#s9Gi{Z{hbC7zc1eI#|ZQH9{*;R5z=>(-zn-TuW>;t z{2fE9a@z-9<;n{&vT;tBnRDR7fgf?xjki&a0i@+CtpURq75Dcnk$SMIVuf?$1Xj1 z7=Pz?k%Gz$1hj5MDCRy%-DkuDkizrtB88I>T_|BgwyoyHX{+rYUAKz9Z^MzOK)h7V zB>kihHQp-M1akSaD2?~IHH@7*nxq;2r6Fwp{xje|Ks-knJ52s-=ey%8-r9Flmt>l@DrdOQ_W>w&>#Hb{N+r89s9Eq%OfyL=8VL zJPQgU>#Oqxdp#DOkAHf;ccSJ(2#@!g_I9&)H;@@NURYU}v}jBaY!~L-XJY0ya*cqX zs&asSj9DYQo>4u^U|&^zG<#QYdB@!?uM~Oxwy5XZJ~+&6p=kt&8Q%2KP8MkU z*lpRKTfg#}tj+p5`0j{*K~J746LG;sfvX)?tkRm*_gpGnrzdnFkK|B_u46^C)E(!A zQyooM?i|cFN^q)V)GmAzZ`Z2692F{B!96t5Vin2H7G8FvySCz{nYCD=ut#ynBVF;C zU1@KYA`WkJp7(!|q3X79y|lWz`e^P-1#%LXdp$?As-O8N35a$FPN;<(q(qUgOcuSJ zc9M(XI98z6kVAX5cH1mSFtehx&cldQ7Q^r84qRDTFx5M8z=lYx-y5D`6Mh=dc{eLr z&54a~*$)rIViM2bysR|Q9=1N}Q*f#j1jXu*RF~Hd@}UIh;bRUByn~}i$?aF!hbEAv zt?l&TWiyGk{mfj>@t;N>J+wA6b4%$@{TTITr8deo&o55UC0nD&c~-~};o)_Rq=esL zyk6G2M1P9pMw^yHJpbB4-{V{-@2&|o59{OUo%?1--;SwOI8mag1W~9X)9Vo(z0T(D zK@arsTwa{ImDbkYs9)UGYwonjwc5jih%r22{qZE_oWS_V#g`AWFGGoI|8vy(Gt>Ie zdtd^q3Qa!JRl$72M;&_H=8?Pmvr`KXh8juwCrS_KRvcgs4@m8;@L@?`hUrI(3K}QA zS=v*pu-v0RU8ghiL47f1{OR%DsxBWGJj=yldX~A*7UZ|fE8P_Armd;3jKszZr{x_+ z(sF`g4lI_6XY1ALxp-S}4(G#&*mJ=~`lx+A$fgCRuX7VDu4i1tbBPWSwJJ&|dV8a! z=D-p!)z~!N;zv55B+M}`bvAjzgVpA7hj#lJ@weKgN4z@N;xkhaWxTUNbO%{~0@$~C zW$Amw+Rvr;Dt*?jkb?32Ix?5hOu<-xt+)r82DAAJ#PFu(p&$||akmA9#+7ZRYp*$k z$NhZ((KmQkA+b1EH)OSvZ{Qkx18GrG9FLV=HZBzd{nXirj=Cqluy&0=Z5z#u@V%^L zC(kz3`82a$DzXmEq)O4!cMIu#VWQokUCG&8x4ZWR&XYJ?uQ$`VC5rO8OpUQ2VDB+- z5#gYrFXdf~TsqX{<70hMio)&5@?xV$0xJ)|Q(bGz6BGUJ7I|`YO{e`n1e{P2tG$s_ zl}lQfBfM!MsyB_ZsaP|4sUx=*8eE%CKgzV$;{w8^ z_PChvS+)q+!8*se*GX-s{eoYc7FMrzzrHIsVq(17GgY}Cu7?U55v$A`oV*1K_0Wi~ zo1SiasGK6%NWfYZy4|gAMi^*yj&z*Mc;5JA6-7^->p~8afY|6|Pn~DlV};Ws>J{)6 zHTo64`YXI#*~QQMA6oUiS@EAmT1Que>@#TWzto~&kv3}YN zh^)7YE%t^PV`mEBO+TKsrt5#0 zl3rU(pWK$>Bp4#vyL-vy;3K=ak4Ui-2MiN(*4IUI?liwwnR^3V)Qhtt?w?*ilx25% zdK18oJ~u)g(BAwm!Q3ku z9JdjZt>4Y1_XA2mP%?D?BnOG-KUGWQ_(@5wF??$aXM1vLb5o23NZV}kDraioY_5E=*JOgq|~czQC6BY6Ih@3P=> z-8L}rP{pinAi{>Zr8e#??icNiDn|c!0q02533L{-$tGl;&?rFxPu2R6LNiFZlG!Fn&VP<3+ zM;orf>GLU8-t8FYZFCAM_z;9B^f8D29>rOC5{QrK2XTp zLGD;8mnhWbHk+cO98PVQembb~I>c~+T1Lk+#<2TEJm}5ny{_-Jjsy4B7y^|GjPKG} zxOBjEKv?(8RwWavwR^72i@{kh(iz@7zy`Rj=*2K&NK40?c#Z2RkUa!sCl;kU#tTb?q`2(}cY zXTys@Shgsu=Ivt2EnV#;DIq0T&?uSJ7+>yLcV{QyAiT_nf+((y6lY(gYEd%>$)H`E z)}YYL&AnrGQ(@i3W9BHEk+zJCw#h3&t@RlI>p;s9{G;Z3#0A z7GBHcpLr?XMK3f7n@^Z8yytab*f*(RguVI52J!DVu=FrIcA(ew{VtuM@w`ED2Y>? zkqPYV)-OeOhyPLmli}r}I%swVscIcJwA(dX_tHoeaoYr&CB6 z1)GUCiqt=(K5no^xs7OaJ#EuI9G$S5V9vvoK{=4QgNd-B;T@1fS2=D7dq^ASYyWmYSj#9O-C|uYL+NO$+`ccyAkiGc_fu zln;bM_S=Y9fx4Uv&v56{P;RCipBze-wH(S|^ad!QYk6k|SwH%sIyN>_7LH$Sz7*c; zS|g(!=5}e$v}DdSRC?B;b*HfM%iXlz#aGIylw0u1Emvw1S5Db8q-6*4wcV9|ytpx3 zlWeMeCqd4^>^>RL#a*%}H-C$yNSa8{qDqNY($gTdS;{jVPK+B!yzna6y&n{)aOY91 zeew;gG^Zl9>&81-#JaIrGnAGd6Rmzselc51y)u$J&G>EVr`P56N=!qhrx>kUWZxMH zFRRa8t8R$rZ@II{mY?}>oF|OA1iX!Yuwbisdsan_f?Vu=_n0X4+HG!(4^F0oS||X_ z+Sy&_yInH!IUd;9g>l4$Y*>QiF0r#L3>CcYD+{CAdW#QC;O=H7a8lhh8I23hZ9BaH z#%Lz9Yd$j`Dn)K`r%3mZE;+@Oh!<{*jeVdlgUk1bdL-?In>@inOU4e%V>$ebH3xz{ z_rE?AOvnfbl~sHek0H{-LrLPkS?ZuZ`o`rOweI`w$ZYvCoL6MNmc1V$Hm#nn95^Pk; zYIxry$XgsBuXa7rY!Y9QV)D&vHoR2$g|(MADfxz8-ZVQ96_S-q{3f`!`B?9C!n}Y( zqu_k*pwN6CAAD3=rCCbK2ULLJi+Ck-r>ymUsuRqo$t{xx56(*1zPh;! zh~Mi3<%Lja{4FoPUgTFNeVKql?a1=ZAb1^d-cL z-X;)+94k!5eSrHxBxtc@70-kS6oP>=K7k-j1%XMQg5ifLo$5yMAND{?4w0(V!2(S+ zoFP#}?Lvz+3i&xjW9ASI8+4r}O;0SJXS+QA7zgAda~+CCv@CkducFJpf$L8wn5;b9 z1x36Z%lBdquTGNK5d}UJvYGOyu6l4UVYqvB+<|{_5flL$(KGRS)y%bIxVLDzj6EG+ z8p#O0ek2W)oZST+b=CEeFc~JR!FY!RbVZ}D@XGtqt+cEND8>XFV6>)KDBaOnL85bn zS@e9RkFC}2POB=iac+-k?#Gt|Cd=VnV>vzJLHy%98+K0r3{>egt~DHp#G%jNS*f^C zpD5fT7thxc?>5&y9zWrFZ+X;6c%(sieWgBC2blYK@cKeK3YkL z{e?QW`VdyYXYjNS!e~3lY(re8YUm$#WH#{h?RKcxuUak_)C&3~-wFy^EFm8#MO0n% z31lEv)&&PNTyf(Hdrc_oW+BAIu0PJrI+AtTy7t(;a+zxpplt6fAcgyCX>D=^rV$jm zOLFyosh0}hZDaO}J(8v`mM^e)MyZ-&EzWPDDm1EsS zE*!8t!I6@+k&<4zlOtGpeF)z2x?&ko4d!c{!^# ziOZVV0>}26KqatRQn&7|gOQ$|%<)*x8IQARs2L}VP%fJtX)8F$Zdfko--;b<9c>Eb z)Cs@(4|;%JxTCWeu5&e!^xy@te4*|A#SVFlGTOTId%J1{C(QWpEvNi5yajey1Hxf4 z^_=UmY8+fTuy-;NGS)}2?l@=W*J;R*LS>c@`y`0SpEcp&S6_YeNY@)eABO{F9y#Oj zIJNY(mA{&L*V|hW(4|^DwSOKI&t_i@DF>Skd=j2cn!azWJMs!Gw2D(7EohnWvC#ww zfTKWFmCqq{8I^H)GXsfBXV+p_nL}Y8nf$OfRO?&%2*}-+_JGAYDDW?cwa7oFxmCjA zn#eslKiNYYHMC&!3hZ!!tpXm1!e7RlD1?37MjMAGaiz2vZvijx%ocD%DHqtE>R1YO zQ^Q>y-U@Ge9(_6d(h%XBSR8t0Njy+%xupZzXc&>2(*^bJ&YzG?`20hD+CeydkB-pK zLFXKj!ogOB3bI;eD^&U}@tlWdMERC+vN1#Y)(LMtf3o1_sqG^8w2pra|14z;EV496Lat zqfg70zu)$GTUB+nbi|9+G>xw22WPt|saZYNT)|Nf!yNOD?9trblKr-U`ylZ`k=c>n z;O=!Id=5h~rTpqL9|_W{SGn3J`e|pCR${LeJT-00$CR^hP_yY*?sjN8ML#w>0jl&2 z?;3#Oi`&c96NS&BHxAqsOmjvbJ)ge~%q?j@7+l(gyPcUrP>7-yUKAgsjbEols}_S{VdIV z440E$b0SJKZ6B1289r=Mo|r!aqLm4>a4L9Fg}-e? zThHl@COJ){-0lJa38uZ*C*D3~aLLwxIi_aa2~pH{v;lfz8g9br^Vu3 ziXt4TxC;Ad$l5&ilwy7=o?@zt0yrf3Vp~g~V(P~0!^4w(RRw}Ba|S&GS)dXxp(jSj zs<(VJV29g@MdIg|caa!c^}n&|tIPxCtVZkOEmu~A*2!qXg4e0a^H=*Fp~*aeYQ2@! zm+pj?D$*r0fDT{roSPl&9}zDuas`F2^2P5?U-RbPr6<&1hhOxp+T-dy(gW=){+D~` zDNI3;Q*`JjkL&A^X{v|8frWb-dDh6*?DboWvVLo<5?8>IXhLyx@wIaf{y8?p14!ZX zmGR_evvYBybZ&k!uaD(!jJK*h*nV8eqK< z)<%VBn}gzAI6SQB-7RJ?BnIG^HJ-^*6IP==gfLLrkNw%QkZ8DYN zsZ~mv6%4@1POM{pqXioCyC5?Otgxx;QqmySRe}!R!*(OZ%I@91y-n5+4d#FOj#3U_ zRq}j2v8E%VGdq8AuOcEl&;h1OnkK*v|H74n`=BSxpgM;%igsUG;FpaV<Y0#xz6W2Qq6INGKL``GHo-K-(64Q1Pq;%F*>BepF2K-1SN6}MiA z?*IopO@cWYA%}u53P3KNvff=W=(OD_nL<43J1On7V)H_>;qtKbL>Wybh zYf=PTpWp%eqQnE;5}vyny%TMB;hAxo!aPp2^vB3R(BzW@kx&29>#m#V<96Z%r1loU z09wwey(WfCj1VlXxFW6Lar6n zd4d3>z15eKfg~bEc!7McXn52EaC-QHn9{+znpyAbs@7pm2;jH%LBsrXJY8h|kcqQ3 zd+H9(0g!X?Pn&Rih%I!4^JCK;i^^*UEuc!@Qwj+J?dCnjU1?ectuLb4@1cycH}(u; z#^^gheC(>O_N!Yj9-Y)5Q$W zaF$oGasZT;c8zxx%(qh~_OOiY%;@ELaL6>uK5e{Cz(SdK$^yh^!1z`2+z#9caGA2_ zf%k+SH*<^{6Y2#P7CW7k3kK@J57Es8oT@7&49el5=it~!G7#dGdpe?=W$W(1DEwy!Vm(qDIZ z-x_d|8QwHcZskNS4U25m&>NJ8r-s@4TpK75>v1FSoSDe#;O`7-1)v7Hm zEx6N4EDgUPpi5rYtPrr!C#SFDfkIC%yGi-MYftjIw^ZH?BziAb4GthZ_W3}i#&iG) zwn3jO(n$n;wBwH`d3WF}Wn#l}K=G}sL|bW64u%EvzZWKGjJ>o{VZclsTEcjuMC>I) zdddC9j3ntE2XGiS`o4SKLV#VO>RJzSjgEIf&hLrxsA;#RUmo#orB2F)n%G)^voansXIUqX*Dop8vgGIo-a!c!b7$yf-II%r2xJFwvAohuF5)fP z7~fXXEUtI}n?5Z5OlPRZ-&Zs0>ZuTgTS#RCfMo(>LJCbnxcaF+fxWk(McJ$O+9nR9 zXg7*2g!>fM9CI(5NWA{Zie5H~#W{1VV;`6XKJx$@NT!OIx~ET*sFFCZGNQzs)0p;m zkTV#T7>W6BKZd&C+7qx^ox@)3bE8IMsXHT$t>sLs&rC0SYwoeBi92@DEBTN1ZlDuo z^r=(jsy$WP=t^rCSl(SJ8)Tj-G+eumH z$$mNM4268R<+awd-itD8_V-f`Z&|Vs^I;V!*h8ArUbBW+X7M;Nfx79K8qRPNjXY=ktUiMD+POft*H9orJ z3X-S!h&>@ABfg+Ulm!D$DJF?jNODcAQ75kUa&)R6hq>4k1ENBqde!_~)>6}mXg}3e zU2ujX@y7glSZH>CS+*GyQbpK5Cm|3ic0~(T6T8R5MMa^wHGl`q<*fZ?Z;Yvu_ z@{+4^l{YOzJGz{^=17Wh?Q%*5(lscu0%RaZeU%^Aq=Vb!0cwW%*tMQp_e&pQD&iOQW?o^_V{#6l-Ab!a5o%k{*^Sb<&Cl1Dvc6oeuH zI=0CO_g}H0tk^ZE-59VtpG=0ye?$OIWvB%09*Vln)6r#^hIeGrptb9?I-E_q$91JQ zw3ePVtVdzW@TX8 zE+D2etjDhV9E5_GU-YxLPbB~caJJCHqbgqucG?@ZJD-%|h?gLxVj#f9oEAq~2%tNq zxh3p?DYxhG-l#yI?a8xL zGN#%$XDN%BaIcALIfoEHt>^;uxmV`eYJr4jIH8JIK1a9QZ20xaV|mgCpk{UK~y9zwHyiY5L+){!d*mN98k zC0(ggIFZt2$RjBsJEMfI)HFSDrP+A(NG-mlwlbYxs4aM*2qCrj(>#vo6S4ZIXfT=4 zpmL?iezeAiTj?*6(#gD@3Kc-l=qPomlX5hrWYaSc*stww8E7)dG7F*&#mqKN_25=z zw6!Z&27c6!Iw4mlHHF5uN!M@&m64Z7PwfE4$I5mtR_1z57H@9 z?%YA{yTQ6y9E=n-Xc2g_0TG15^k~SSNL8(9&Ll@yH=srg(FEXGFiBR$e<%6(ujB)X zFxJo>NlD2p4~wq+7Kk6lKwPPl4sB@~g98omBQ#QpJs1RAS)cJns@(~Li;pk0FkB^E zaj^=?u46f}>m0MzTXJrQ3T9AEw=Hm(=%#ORbw_TCbOa|JyNu#wH$b$Oveu0;`0`~$ zsT1e!w&vT=(c=fflWt2@2JO5xRimFk6>=AJ1RStUk5{3$nt)S@kK0bVcaU6vu00x& z=NVz8GwM6z_UzI&=zwVa!F^@A;IOF6tP?2S8y_#2um=Z4Q|fQlo^=0E>3n2};CZf9 z-yu$f-bLt8R*QF!&&?-~L8Tt&K;fx~@j53M`m?c)%NthK^ zC#DCgWBJzs-d$d0EFoqCY(i>AnJ$ETqg-{0V4q4z?iSUn1ISw^GBfOQremdqmb-l_ zzj}f6M$VDzsFV|r3$xkQAY^{9)|~;dXw|2By0S^NcR4&9qOBRvKRL>Nq-+>$GSs|% z?!yu}FzCG^fO8Q42HJpc9Hc)r<_$Y_y5Vj7WKP6BVY0~5iVm--6uNGj>XUt-eyI~| zud<(g$K1KH)4Sv)^P#O28cZu6;Eo=MQD(8}yNI6FATs{BJhHmO`$}{&0=&S{&UN{v z<8(BQNjf?ovNKk8`jg`K%xhQmqYg8452(zcDgvAu)h+hd9;QnyVIlbphk35Hf3ljU zOO9khPNkQn_9RgZ*r#UB%uc!qs2{r_SNUj&vEvHCVHU(wqeNR=OKmx+Ixd$>zzaR$ z?LPOU!r+0}cI8w1RLNE<%rX>ur%AHc^jyI^Yb*d3ZZ~JK7IguXVV(x6h?AW*D|qFE z(BoGlPCHm7fT(SZ;;bsQm-pts8M8a1X_nFUn9!Z}rm?4U8sUfK;lxvuRJCi10ha47 z9@liv3?p||I;SH~tgS}%zt9(kH<^CgPoTscAFxWAEYt0?n~mu?ONyyjWfQlDX#zJQ zs~3?%p%;O?R{PNJnuChiIXV3^*WVW&+F#OM2^}GN?45J5S2jYq#;%XYLo}hp^9JB{ z94E)*yj{gk^qpqnsPOSSI63fqy~Bf#*~;KUZ*Kr|_sChhMK>Ys$pf^D1?3a7S6$RW z^;&zxE!ampm$1ecJ^9L-<~2Qg!YPjZf}J%g@dlWaQMvE0xLJr#InS`^S1c4+*UU4c z_N1iyTtkZahbv!E&$xJ^fS4_!cyWJ$tAH?SDUq$1710$1ubT;*zIgET=vlyzgO^IB zACEf0Pw&*TXWm8o_5#d3L*WUn@me-b32txV`lrUL3;RR$h>KLj{8I?Lg#;-^4qnzK z=|Rd>KVm>MapygnO%e5$REuue`?0`mZOmY;-CtC;KPt1ABoR=d!*unP!!CZ|A#_nr z-5by7JuD*XD0H&Prn&?>$WdD`>(G$W)l~4H8}cD?fwb&aQ72wVx17GEuXSU9`O=4* zotfje=dVaw+?$$j2)64fEFqj}wCPu+_Rry398`IG9yYnXu7oqy@n(WYv4o0Qa-#ce zmGG|XI%o2y8~EqXKltPp*>a`#vdtO_iK-%=4r#M`ViQFic7}m*_)1swDuBnjoFoUgHlcvnxF~y$^z~oRl5XS8B2dYO~)S6=FWK z@f<=OeYRzy zZDLGqu_JCO=XQc_$BQ9%;h;@~$l{&m+ly)Q= zoy1%t8c^>%3;=bqp1x>3yDiy6)+^ z&hxyI!-xl@UY>Q)zU$YYw|&^&=0-lrrv36&nG-H<~heL-9})E#fyN6i|kHBNeF}IEq=WNyVToiDIr! zb@B|;OlxSxfX@~2)0ZWk*~&n@$f*L>A}{v9rBlaKi3T~p6G7yHk~H$;I9lQHy|!sg z;OkAxU54gNl0%)cPAW^J|5{~^Y+9B!BsL2-r>I)ucWn7C=q>*Hg;?{wA}%Rur?%iu zQ7Q#J$gR-Uf_EZwjrbbruz-L1|C{@7H@fbiwitz~Eh0B&{B`ol?|cFRxh=s6oYx(z z%d7ttx9W95@cfxUp)8IHgh9Ft%WI4Mg&qedRK7571W z?b_P*TIB$feG~txXqXlyL@?M-_CZ+X+$FI1iqWW$^&=E9gzUyzh8NcoKsd@oYLp{} z7tGsX(srf*!pngAtoIK>Aq#w9t$vAzO$?Oe=(AYisv^~@e&{Gol3b7!7rb!Gex+Tr z42ehUIku~xqdvY5;0Y8k0oK)SNDW)?SpxFohCf5!4xq|Vpr{tvl~>Fh7^bAn=7G(J zKe}2x#3&^i33po^@l`UzJ45kw-3|QpK)BG z3%RgUNCPvNUgySYjkovE5dk=ypU{)d;b#q~KAHTkUeQkop}d9(Mz3c6ChiH;iX%Y@X2Y26{lxDU=kf#8T+5AQymK<;yxm48vpd+(Ff#5752 zK@vMl63*GK?dkvA8bF>`2^#;QBqvuIV3+`4CF}ljm)_tMIhq7=#9qoL#OG`gSnyvj z{!MdeY3zW)3{cY-f#Ahta^3uzu$}s&N@7#`za5xe0{|VTdJXb14#XAabpxD>l+xTy zKs4mLCVdf%COQ425GZ2MM^S|v#yWMI&Cb|h%l_3cPG40OZ^!-Un{!$WQ>KI6>D==A zbBT@L*Rq^(fk!^E?$wrja|oF*b_)-`{$lq#g+;h#+z8X$?LXfe+$ZihDM?H98riuj z%p(mvN_uc^ML!TA)_Q%&1x|>;szpuDouKUb0P?W7rMS8Lfv453Z@{ph*|@gF^zM~d zzwpl;fkQX~Ao=$-t8^-jZ$DLmEqvyE=oCerGt1;>+1%mL6zLdYQ0zkhTDCTKs*XCG zkf8;~ECcM?3n?3Al|MuwrY5w8V6Qy{j4wl&GWihu57By#a*o*BQmgWq-Nj{LFLr(} zP_{nUXS?-%`^T>=zm%9kwHgI2I;vHDDHK3J^vOG8EXQ~6wO7xB?U=vUU7B`g&p8Gr z$2vK;vprW9h^hDz=g=zu5Azg7^+Uu`#UrSQ`~IOtWf)h_mK%V+ij8UxER*_8ys==$C;aQ+61mc=L~CPXk8JdC5&c+ z9bG$K{W-|7)acna3(h)wOgN|c4vN6R<2kaF?b`vV!LCe@uc=4}4KD3wCRwzYw5V?D(ytWMF${pd*w@8xA)nV7IlAQ!iqy?G}A}eyPfL1mmcE zLm%Ld1x5#-X(QpDF>S$afFatg`C#t8RgM+OF((a%1>>9oVrBCK>+gkoFG*}%0lTq; z6U~>8sZJ3JTbkR zcc*h|OEoJu+Ea#eXaHyeDB+PAiycG?lL>SPRP?iXdk|H@X$#WPmzEOiZz*H%61WZd z&=n>y@!#RMQ|pD{ny&Qp6b*!xQUWdCxsBlK1!613TI_^aErRBSnDwkZ0$&$;**LYjR=Kk!;{VAU zKi4g1moYnw7zE8~T6m2!fvOkCC0!P-DI(Z4XKZJmQ;(I9XoOY=fGo*2D0k*5X8}L# z0Eqloq6iOS$#yc)uN0&?YqpjocI?ZmZ!zqmgyXLvTBA6QhlGxKQN0_ZP8!N zjjT})LLi;!el1_%_)UYuK#03j*uxFwSMU(VSi_;XZ{za^RLp`S;cl)Q)bOHFy{@Nq z<<@F<4%tTvSVEg`XB?63=f<@7h;7bSJ-vdh73~joA3BV#*|{)-8XuGA4V3k-WKFX= zbd7doq-R%jHz!C)C>hCEfgXA?{}Wf@IAryPnSM875HPzD;u(TKX2y{@pE|9gzpw}U zcAx$rg3vei--NZv5##zPaF|2(x7~HmHe~}S8&7chdhz$gr(QkpZNY9Y6_b5(-5r;? zWjM67Al_v0@1tQ|NApIzsD#9kZs{D(ZRE8_=q_$RocRW8!a)gE0XPIG0XF3krjx-m zHZ;=^J8i_=Sb_0YmVh5wkT3*0CW)$%nDutSQ;q z{vk{q#?nmn(RJ~0`IlC9IDtNP+WVD>LAh5ccF4DZS3BG8O!NiQnu#jU9<-~ zKc55?a8a1>O~;#U=VnXaC3w7$m9!8yYvz8kK?&!eRd-gsE>upUH6<`3>rl$v%kbgP z(Jwp7OND}^SLocOL)on9$ZlnFWV$%o26<2BA*7SuV5%hEKdST9Vs(}%v=b`{2pEnb zIRZXMM+UqNm!zJI@qFNLVL#A_k_9n>?-*38@%m{C)YAzSyWfAz^qR++!d>?_6?=J_ zk2N|Whg-kjcd<%zY$WK34!a)vvR&Nq1r{Tc2jCV_am zR%=F+sT&9Z6pW_|W*hIdY-Exii12E=)=HA!5!O-u_!tF`(+50DC~&OR`l?32Rf~9? zC3ELPDLqFvUZnGgTO@dPxVA=X{vc23O2Tt$&Txl?hjf?fB=njS%ZU+eu!Am)ML7Ov z>BA>_qwqg7ZfsMqHE+IZp!Z+QyW=7a50Mc8C>> zx6htbC=y&&*3@ zxYK~JP=NxzXVh(}t()*YlRIYizi-z)Ip*KG$43icRTp-g`s{9}UugLh0b$KloMDhG z&e#QxIekHpj^W&zNH&4aU_nbyp%o?};Z;A_i*>%G&Xkv)iOkk5`p_IF+KDjM;E=@D z5Mre}@Ius|%&gwqA(d~7g$XcTJ$a_8t1a}h=15bzO!O^;wW)%+eU2o{eZWZ}S-3NG}@B!D_=36Owh!xH7%xQBy(7rXmLI& zWO-{#Dt)HD$o#B%b6#_KLu~O0=F0Ekq*&_RBnEKYhl~e0g|2EroOD~rQ3#@K_WcCw zcTSr$)x9_8@2|^SlHMjJ>9T={id&}l=+fd!AGeCfT_pZD(_PRAi3vQzL(+VzY^g5G zJZt`L7iC=(rx`iE2%`H-t})y_R^LRMzHsMZ5bZtrugBBZ&1|nG9E)W5?7@tfev8o3 z5r^T&>IGeSre*EvnvafGQ;-y3KjB#I$=da zO>`x_<^7`k8z~}7<9R$nH+#&=&M&&ur}<{+1PR8oD@DET6fdz;L-Qw0vA_5$e}aNB zMT2VB;@aH!h}+c>%`>hAGy8+84-!8y9j$fY&-N(iXT5m|5KfZ9aAn$Qf7zKik@{f_ zGAWRkSZ;5&j>{F;#kD<>=Vq5Vf`yA&sK7kqfYx0It z-LVnTX6eoKR;R*dYp-q_8bsg#TQ-hJHMHFKdR!Dm%Fk+evHbh|4(+*I!(4#!;Upo; zL_m@H;fL=74s+)k)p(=%8djRpBe|kNOx|-{fjeVAbYm?9?~tlBkGX)-!Pml-L_K}@ z)2j4?&S_Rb@wW`` zb@j+3otw;B)!x<26ULD0fh_;*BT7IsH;;XH@j%56iHgp~cXt$ht+*j|s5dxV=SBky zNR+-%EZDkZrDE-9quGR=8fTV_45xP4uBxQJpn(}JCrf=WRE84p(RI$gqGgSauo?J=J z+=p{3bYB@zOe4UQ48qKVZ!L`q)_LDC`Zjb3fKd{*-?eJo1B&eZ7ebVef$sVg)#*=j z+6Sg1nSk97QqBCeb@}sw3`)A4rl@kt%tfqofeAyMy1RLKRP5TLOVB z#;10nLz=;1?YNJfX?COgy%s?@aWUi6tQlHtwP9a)Lzk;<#FX)yxIsFqta~3P(3XR z^~Z;fz`Q>=h-XRuR)q<_rHoROcb2b!EYXW=#_QoD#*Ucff;2`K>1Se~@g&9_=!QQH zBopXwxtI$>HGhU4+Yp6bv`jfG-URetLw z^B^4JB7ImvF2k~il!RR}Ztri5XUp;Dt~$0uSuUX08?01PH_u&LKczou0cd4kNf+p3 z7Y*7q{C;ehGpjIWi4#$D6c|*Q-$$x>;nuP`3lXOz3m>S!^9|Mw;cY;MH}Q5e*uZV$ z23cQ&vnm>EQU?ETdcT_9iB05c@@_M-@Xd1865R0Gn2A8s?n6w-vY%;@+pQ9jvdn8g zaJBh}xFHg4I)lWb@>O`^{lA64|&`<`6sJ%wgSwwi?wJ&LD z)bPrfVVZx}B~c;x4vQ`SJMl|UTtIej(Dg9jKCoAsMHc*2YJY^EhbW^Sl2t{~3NN7< zNS2BUYyztK@1#4GW`-w1KF;v|oK*KVmHHpTfVR2{coET_`v=a|AZ)MbBYi^&dv)1A>6WHKBxAWJt8I{3Z5B@B548?n@I{`7cq*?LWojy zA7@I8)3q+C!9fm~ChN*`kg272ajdb=V5{Ar1i2T0+XwY~&aPx*-MyP`Q4^gbJq2=Y znK}gx_5Mmh4?g=uJ?5?jJL zINSVZfr-t1_RA1XL59jtJ>(DBmj*Da)nHc7H29O{r0bZe4dx%cIuIdHHpscX_#PGMtb;B{%7`5~%;b}W&h5GW3vm!UPwx=0Zx_d%31vCV$)OW0 z;Ea404u!s7yLU_7uN;k=K@Xpgx)LP58A(Xj1DaB|P54QY&}>6LgO|yWI znuKj+IoJ(qO0s|-9AGu?i=Y4Ud#?j1i}9S;=2wtTg#{aZLy`i8?*`dkLNh4sK4(Hx zaXH*sZ*$y5`XZ|{Jvd{dLg+_=g^=}rx4?5sC|r4d{w1)|@j+Gi7k(56!T+Ag>Q^#m z6pG0i8dB~2}(_tys=peSm8{@GhJfA!0=DzpU$D6ypn{%imX70P&`HtPL^WX<{6FMcS{fa%z_ z1Jhq0_&?UMOzbQi@xa?J1}bu}npTl@T#Tr5)=^Ng3RCLZN*i3sDYEPuexdYKjg6!h zKiu+YXVoXZvqnZMnw5p)Sl6xwW!M&0+y07ECD&6!skF-@Xdc6MbR63+9=L?SO)bSA&8_c5DdY&9ean40uJaJjp;^~T`| zBbTKS<=WkhD5tNUNawG}tPkTT(<^g&IIfjb#)wb5C4J3iZf*MU`WK5~vXSYDChA!M zJ!JNLJVN-?Xzbn&B3XgpCPAd4-;~W5QMZKPaMwWfm$oBvItV^dA+~;i z>N=Y-scDDTf+QVctRx(R%5~NLG?z3n<*X-<>`w@yC*!9FEeLvdCmE$GNc)i&PR`H7 z5$Eu@Y^6i@^a#rjH{wtO*3dgOS{`FnF;p)4dx)v;(tku+0`We8nAIwJ&H}*4ie?_v z>-UDX2Q|kCmw_np%uQZnpQK{=TMOuMxo7YF!WQw@&3JZ&!oSyqjhpYh28JdVvM_j2 z))zHDTtzH5Sq5cbnu)d10VsgLtDJ0sn`Tjn3p=9;&sebU8Iu&|+O-{a_*kN?I)2DK|BJEZ(Tn6{OBM1;=|vpX$3w-Gee?g#SG zRm;q!?i1rLbG{Ru^Lp8Y8^0!A6+oAwG1g1=Ki`IL>!BDX2i$Ly62E-l-?OrVI|T-Q zas=-rsYn8MB+dXL>@;Zh^YIU5Q`p?hH?dz>o?QzUxY*!(G|Kw#= KWU{2L-}?`Z5Wn;Q literal 0 HcmV?d00001 diff --git a/doc/dev/design/index.rst b/doc/dev/design/index.rst index c27ebde16..bbc2d2954 100644 --- a/doc/dev/design/index.rst +++ b/doc/dev/design/index.rst @@ -40,6 +40,7 @@ Active uri grpc ColibriService + BorderRouter .. _design-docs-completed: From 71c6a5c1bd40648cf08adde5513a02ab55f95d06 Mon Sep 17 00:00:00 2001 From: jBainMartincoit <135358449+jBainMartincoit@users.noreply.github.com> Date: Mon, 5 Jun 2023 23:50:06 -0700 Subject: [PATCH 028/255] doc: fix grammar in dependencies.rst (#4349) Fix a couple grammar errors with past/present tense and capitalizing the nouns. --- doc/dev/dependencies.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/dev/dependencies.rst b/doc/dev/dependencies.rst index bbeb02377..9f236cd13 100644 --- a/doc/dev/dependencies.rst +++ b/doc/dev/dependencies.rst @@ -28,27 +28,27 @@ To add/remove or update dependencies: 5. ``make gazelle``, to update the build files that depend on the newly added dependency .. Warning:: - The Go rules for Bazel (rules_go) declare some internally used dependencies. + The Go rules for Bazel (rules_go) declares some internally used dependencies. These may **silently shadow** the dependency versions declared in ``go_deps.bzl``. To explicitly override such a dependency version, the corresponding ``go_repository`` rule can be moved from ``go_deps.bzl`` to the ``WORKSPACE`` file, *before* the call to ``go_rules_dependencies``. - See the `go_rules documentation on overriding dependencies `_. + Refer to the `go_rules documentation on overriding dependencies `_. Python ^^^^^^ -The python dependencies are listed in ``requirements.txt`` files. They are generated with bazel from the -adjoining ``requirements.in`` files. +The Python dependencies are listed in ``requirements.txt`` files. They are generated with Bazel from the +corresponding ``requirements.in`` files. -The python dependencies are listed in `tools/env/pip3/requirements.txt +The Python dependencies are listed in `tools/env/pip3/requirements.txt `__ and `tools/lint/python/requirements.txt `__. -These files is generated from the adjoining ``requirements.in`` by bazel. Only -direct dependencies have to be listed, the transitive dependencies are inferred. +These files is generated from the corresponding ``requirements.in`` by Bazel. Only +direct dependencies need to be listed; the transitive dependencies are inferred. The exact command to update ``requirements.txt`` is described in a comment in -the header of the file. +the file's header. From b2fdbc79ea5abc8298f1c36731061435a935184e Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 8 Jun 2023 19:58:03 +0200 Subject: [PATCH 029/255] slayers: fix decoding and serializing wide DT/ST (#4352) Both decoding and serializing of the address type fields (DstAddrType and SrcAddrType) was truncating the most significant bit. This has not caused any issues so far as no address type with type greater than 1 is defined and used. This bug was introduced in #4160, by consistently using the wrong (!) value 0x7, instead of 0xF, to mask the lowest four bits. Fixed the same mistake in copies of the serialization logic. --- pkg/drkey/generic/generic.go | 2 +- pkg/drkey/protocol.go | 2 +- pkg/drkey/specific/specific.go | 2 +- pkg/slayers/scion.go | 6 ++-- pkg/slayers/scion_test.go | 64 ++++++++++++++++++++++++++++++++++ pkg/spao/mac.go | 2 +- 6 files changed, 71 insertions(+), 7 deletions(-) diff --git a/pkg/drkey/generic/generic.go b/pkg/drkey/generic/generic.go index 4c2ec9978..d6e20cb52 100644 --- a/pkg/drkey/generic/generic.go +++ b/pkg/drkey/generic/generic.go @@ -94,7 +94,7 @@ func (d Deriver) serializeLevel2Input( _ = input[inputLength-1] input[0] = uint8(derType) binary.BigEndian.PutUint16(input[1:], uint16(proto)) - input[3] = uint8(host.AddrType & 0x7) + input[3] = uint8(host.AddrType & 0xF) copy(input[4:], hostAddr) copy(input[4+l:inputLength], drkey.ZeroBlock[:]) diff --git a/pkg/drkey/protocol.go b/pkg/drkey/protocol.go index b7676a776..ee3fa596c 100644 --- a/pkg/drkey/protocol.go +++ b/pkg/drkey/protocol.go @@ -102,7 +102,7 @@ func SerializeHostHostInput(input []byte, host HostAddr) int { _ = input[inputLength-1] input[0] = uint8(HostHost) - input[1] = uint8(host.AddrType & 0x7) + input[1] = uint8(host.AddrType & 0xF) copy(input[2:], hostAddr) copy(input[2+l:inputLength], ZeroBlock[:]) diff --git a/pkg/drkey/specific/specific.go b/pkg/drkey/specific/specific.go index 7d4dfc326..b156b2f6c 100644 --- a/pkg/drkey/specific/specific.go +++ b/pkg/drkey/specific/specific.go @@ -96,7 +96,7 @@ func (d Deriver) serializeLevel2Input( _ = input[inputLength-1] input[0] = uint8(derType) - input[1] = uint8(host.AddrType & 0x7) + input[1] = uint8(host.AddrType & 0xF) copy(input[2:], hostAddr) copy(input[2+l:inputLength], drkey.ZeroBlock[:]) diff --git a/pkg/slayers/scion.go b/pkg/slayers/scion.go index 5bf3df217..86343d758 100644 --- a/pkg/slayers/scion.go +++ b/pkg/slayers/scion.go @@ -183,7 +183,7 @@ func (s *SCION) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeO buf[5] = s.HdrLen binary.BigEndian.PutUint16(buf[6:8], s.PayloadLen) buf[8] = uint8(s.PathType) - buf[9] = uint8(s.DstAddrType&0x7)<<4 | uint8(s.SrcAddrType&0x7) + buf[9] = uint8(s.DstAddrType&0xF)<<4 | uint8(s.SrcAddrType&0xF) binary.BigEndian.PutUint16(buf[10:12], 0) // Serialize address header. @@ -215,8 +215,8 @@ func (s *SCION) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { s.HdrLen = data[5] s.PayloadLen = binary.BigEndian.Uint16(data[6:8]) s.PathType = path.Type(data[8]) - s.DstAddrType = AddrType(data[9] >> 4 & 0x7) - s.SrcAddrType = AddrType(data[9] & 0x7) + s.DstAddrType = AddrType(data[9] >> 4 & 0xF) + s.SrcAddrType = AddrType(data[9] & 0xF) // Decode address header. if err := s.DecodeAddrHdr(data[CmnHdrLen:]); err != nil { diff --git a/pkg/slayers/scion_test.go b/pkg/slayers/scion_test.go index 352398024..4ee604668 100644 --- a/pkg/slayers/scion_test.go +++ b/pkg/slayers/scion_test.go @@ -16,6 +16,7 @@ package slayers_test import ( "encoding/binary" + "fmt" "net" "testing" @@ -390,6 +391,69 @@ func TestParseAddr(t *testing.T) { } } +func TestUnkownAddrType(t *testing.T) { + + testCases := []struct { + addrType slayers.AddrType + rawAddr []byte + }{ + { + addrType: slayers.AddrType(0b1000), // T=2, L=0 + rawAddr: []byte(`foo_`), // 4 bytes + }, + { + addrType: slayers.AddrType(0b0001), // T=0, L=1 + rawAddr: []byte(`foo_bar_`), // 8 bytes + }, + { + addrType: slayers.AddrType(0b1110), // T=3, L=2 + rawAddr: []byte(`foo_bar_boo_`), // 12 bytes + }, + { + addrType: slayers.AddrType(0b0111), // T=1, L=3 + rawAddr: []byte(`foo_bar_boo_bop_`), // 16 bytes + }, + } + + roundTrip := func(in *slayers.SCION) *slayers.SCION { + // serialize + buffer := gopacket.NewSerializeBuffer() + require.NoError(t, in.SerializeTo(buffer, gopacket.SerializeOptions{FixLengths: true})) + + // decode + decoded := &slayers.SCION{} + err := decoded.DecodeFromBytes(buffer.Bytes(), gopacket.NilDecodeFeedback) + require.NoError(t, err) + + return decoded + } + + for _, tc := range testCases { + require.Equal(t, tc.addrType.Length(), len(tc.rawAddr)) // sanity check + + t.Run(fmt.Sprintf("src 0b%04b", tc.addrType), func(t *testing.T) { + pkt := prepPacket(t, slayers.L4UDP) + pkt.SrcAddrType = tc.addrType + pkt.RawSrcAddr = tc.rawAddr + + got := roundTrip(pkt) + assert.Equal(t, tc.addrType, got.SrcAddrType) + assert.Equal(t, tc.rawAddr, got.RawSrcAddr) + }) + + t.Run(fmt.Sprintf("dest 0b%04b", tc.addrType), func(t *testing.T) { + pkt := prepPacket(t, slayers.L4UDP) + pkt.DstAddrType = tc.addrType + pkt.RawDstAddr = tc.rawAddr + + got := roundTrip(pkt) + assert.Equal(t, tc.addrType, got.DstAddrType) + assert.Equal(t, tc.rawAddr, got.RawDstAddr) + }) + } + +} + func BenchmarkDecodePreallocNoParse(b *testing.B) { raw := prepRawPacket(b) s := &slayers.SCION{} diff --git a/pkg/spao/mac.go b/pkg/spao/mac.go index 898cc4f26..d594ef88d 100644 --- a/pkg/spao/mac.go +++ b/pkg/spao/mac.go @@ -137,7 +137,7 @@ func serializeAuthenticatedData( firstHdrLine := uint32(s.Version&0xF)<<28 | uint32(s.TrafficClass&0x3f)<<20 | s.FlowID&0xFFFFF binary.BigEndian.PutUint32(buf[12:], firstHdrLine) buf[16] = byte(s.PathType) - buf[17] = byte(s.DstAddrType&0x7)<<4 | byte(s.SrcAddrType&0x7) + buf[17] = byte(s.DstAddrType&0xF)<<4 | byte(s.SrcAddrType&0xF) binary.BigEndian.PutUint16(buf[18:], 0) offset := fixAuthDataInputLen From 156957609f256d354e426b9a3cf4058d22f8c6a4 Mon Sep 17 00:00:00 2001 From: jBainMartincoit <135358449+jBainMartincoit@users.noreply.github.com> Date: Mon, 12 Jun 2023 05:11:23 -0700 Subject: [PATCH 030/255] doc: fix grammar in git.rst (#4350) Fix a couple issues with tense, nouns, and punctuation. --- doc/dev/git.rst | 89 +++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 47 deletions(-) diff --git a/doc/dev/git.rst b/doc/dev/git.rst index b0897ffec..c932f2dfc 100644 --- a/doc/dev/git.rst +++ b/doc/dev/git.rst @@ -9,11 +9,11 @@ If you've never used Git and/or GitHub before, GitHub assembled an `awesome list recommendations to get you started `_. Below, you can find some additional guidelines on how to work with Git when -contributing to the SCION project. If you never used Git before, we strongly +contributing to the SCION project. If you have never used Git before, we strongly recommend reading it. Even if you are experienced with Git, we recommend at least skimming it because -it includes some additional information on how to write good commit messages, +it includes some additional information on how to write good commit messages and how the code review process works. Forking the repository @@ -24,17 +24,17 @@ do this by going to the `SCION repo `__, a clicking the 'Fork' button on the top right, and then choosing your own personal repository. -This gives you a complete copy of the main scion repo, in which are you free to -make changes without affecting anyone else. The only downside to this is that -you have a little extra work to do to keep it up to date with the main repo. +This gives you a complete copy of the main scion repo in which you are free to +make changes without affecting anyone else. The only downside is that you have a +little extra work to do to keep it up to date with the main repo. This is covered below. Setting up github auth ---------------------- -Interacting with github using git will require you to authenticate every time. -In order to make your life easier, we strongly suggest setting up automated -authentication using an ssh-key. Github has a nice `doc on how to set it +Interacting with GitHub using Git will require you to authenticate every time. +To make your life easier, we strongly suggest setting up automated +authentication using an SSH-key. GitHub has a nice `doc on how to set it up `__. @@ -42,9 +42,9 @@ Cloning the repository ---------------------- Now that you have your own fork, follow the steps in the -:ref:`setting-up-the-development-environment` to set up +:ref:`setting-up-the-development-environment` section to set up your workspace. When you get to the point of cloning the repository, use the -directory the README indicates, but clone your own fork into it instead: +directory indicated in the README, but clone your own fork into it instead: .. code-block:: bash @@ -53,50 +53,49 @@ directory the README indicates, but clone your own fork into it instead: (If you have authentication setup correctly, you won't be prompted for a password.) -This will initialize a git repository on your local machine and pull everything -from your forked personal repository in there. +This will initialize a Git repository on your local machine and pull everything +from your forked personal repository. Keeping your personal fork up to date ------------------------------------- -In order to keep your personal fork in sync with the main repository, you need -to add the main repo as new remote repo in your local clone. Github's `guide +To keep your personal fork in sync with the main repository, you need +to add the main repo as new remote repository in your local clone. GitHub's `guide for this `__ is -pretty straightforward, but can be summarised as: +pretty straightforward and can be summarised as follows: .. code-block:: bash git remote add upstream git@github.com:scionproto/scion.git -Now that you have this setup, the `procedure for doing the -sync `__ is pretty +Now that you have this setup, the `procedure for syncing `__ is pretty straight-forward: #. Fetch the changes from the main repo: ``git fetch upstream`` #. Switch to your master branch: ``git checkout master`` #. Merge the upstream changes into your main branch: ``git merge --ff-only upstream/master`` -#. Push the changes to your github fork: ``git push`` +#. Push the changes to your GitHub fork: ``git push`` .. _contribute-submit-pull-request: Submitting a pull request ========================= -Pull Requests are a powerful tool provided by github mainly to review code -before it is merged to the main branch. +Pull Requests are a powerful tool provided by GitHub mainly used to review code +before it is merged into the main branch. Preparing your pull request --------------------------- Before you create your pull request (PR), make sure your code passes the unit testing and linting checks. -Run the tests using: +To run the tests, use the following command: .. code-block:: bash make test -The above runs only the unit tests. As soon as you open your PR, some additional tests +The above command runs only the unit tests. As soon as you open your PR, some additional tests will run automatically. To lint the code, run: @@ -127,48 +126,44 @@ Here is an example of a good commit message: Fixes #3766 -- There is `` at the beginning -- All letters are lowercase +- Starts with`` +- Uses lowercase letters for subject line - There is always a reference number to an issue Submitting your pull request ---------------------------- -In order to submit a pull request you need to push your branch containing the -new code to the github repository (as explained above). This new branch will now -show up in the web interface (under 'branches' on the main repository page). -From there you can click on 'New pull request' where you can add a description +To submit a pull request, you need to push your branch containing the +new code to the GitHub repository (as explained above). This new branch will now +appear in the web interface (under 'branches' on the main repository page). +From there, you can click on 'New pull request' to add a description and check what's included in the pull request. -You can then assign the pull request to one or more reviewers, which will get -notified to do a code review. +You can then assign the pull request to one or more reviewers who will be +notified to perform a code review. Code reviews ------------ -Github's code review interface is fairly basic, and is missing some key -features. To compensate for this, we're using an external review system, -`reviewable.io `__. This integrates into the github PR, and keeps -track of comments that have been addressed or not. When all issues pointed out -by your reviewer are fixed, your code is probably ready to be merged. +GitHub's code review interface is fairly basic and lacks some key features. To compensate for this, we use an external review system, +`reviewable.io `__. It integrates with the GitHub PR and keeps +track of addressed or unresolved comments. When all issues pointed out +by your reviewer are fixed, your code is likely ready to be merged. Best practices -------------- -- Keep your development branch(es) rebased on master. -- Squash your contribution to a single commit before sending a PR. -- Incremental updates to a PR should be separate commits, as this allows - reviewers to see what has changed. -- Each PR should be self-contained (as much as possible), have a description - that covers all the changes in it, and always leave the tree in a working +- Keep your development branch(es) rebased on the master branch. +- Squash your contributions into a single commit before sending a PR. +- Incremental updates to a PR should be separate commits to allow reviewers to see the change. +- Each PR should be self-contained as much as possible. It should have a description + that covers all the changes and leave the codebase in a working state. -- If you have any git problems, ping someone on the slack channel for help. - Don't suffer alone :) +- If you encounter any Git problems, ping someone on the Slack channel for help. + Don't struggle alone :) Final comments -------------- -Git is a very powerful tool and this tutorial barely scratches the surface. It -just presents the most common use case, but it should get you started. Please -use the vast amount of really good git and `github resources on the -web `__. +Git is a very powerful tool, and this tutorial only scratches the surface. It presents the most common use case to get you started. Please explore the vast amount of excellent Git and `github resources available on the web. +`__. From 8bace733b17dc534f9d4925994fe2851cd89f6e0 Mon Sep 17 00:00:00 2001 From: Lukas Bischofberger Date: Thu, 22 Jun 2023 10:28:38 +0200 Subject: [PATCH 031/255] fix spelling of Daemon (#4354) Fix misspellings of the Daemon, was spelled as "Deamon" in some places. --- private/app/flag/env.go | 2 +- scion/cmd/scion/showpaths.go | 4 ++-- scion/showpaths/config.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/private/app/flag/env.go b/private/app/flag/env.go index 964534f62..a585a9017 100644 --- a/private/app/flag/env.go +++ b/private/app/flag/env.go @@ -106,7 +106,7 @@ func (e *SCIONEnvironment) Register(flagSet *pflag.FlagSet) { sciond := defaultDaemon dispatcher := defaultDispatcher e.sciondFlag = flagSet.VarPF((*stringVal)(&sciond), "sciond", "", - "SCION Deamon address.") + "SCION Daemon address.") e.iaFlag = flagSet.VarPF((*iaVal)(&e.ia), "isd-as", "", "The local ISD-AS to use.") e.dispFlag = flagSet.VarPF((*stringVal)(&dispatcher), "dispatcher", "", diff --git a/scion/cmd/scion/showpaths.go b/scion/cmd/scion/showpaths.go index 54e328299..b0cd4480c 100644 --- a/scion/cmd/scion/showpaths.go +++ b/scion/cmd/scion/showpaths.go @@ -61,7 +61,7 @@ func newShowpaths(pather CommandPather) *cobra.Command { Long: fmt.Sprintf(`'showpaths' lists available paths between the local and the specified SCION ASe a. -By default, the paths are probed. Paths served from the SCION Deamon's might not +By default, the paths are probed. Paths served from the SCION Daemon's might not forward traffic successfully (e.g. if a network link went down, or there is a black hole on the path). To disable path probing, set the appropriate flag. @@ -155,7 +155,7 @@ On other errors, showpaths will exit with code 2. cmd.Flags().BoolVarP(&flags.extended, "extended", "e", false, "Show extended path meta data information") cmd.Flags().BoolVarP(&flags.cfg.Refresh, "refresh", "r", false, - "Set refresh flag for SCION Deamon path request") + "Set refresh flag for SCION Daemon path request") cmd.Flags().BoolVar(&flags.cfg.NoProbe, "no-probe", false, "Do not probe the paths and print the health status") cmd.Flags().BoolVarP(&flags.json, "json", "j", false, diff --git a/scion/showpaths/config.go b/scion/showpaths/config.go index c6419d468..bae04756f 100644 --- a/scion/showpaths/config.go +++ b/scion/showpaths/config.go @@ -26,7 +26,7 @@ type Config struct { // Local configures the local IP address to use. If this option is not provided, // a local IP that can reach SCION hosts is selected with the help of the kernel. Local net.IP - // Daemon configures a specific SCION Deamon address. + // Daemon configures a specific SCION Daemon address. Daemon string // MaxPaths configures the maximum number of displayed paths. If this option is // not provided, the DefaultMaxPaths is used. From 5f7802c20ab75f726b5fb2e7e3c883dc661016b5 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 22 Jun 2023 11:56:43 +0200 Subject: [PATCH 032/255] doc: update generated command docs (#4355) Update generated documentation by running `make command-gendocs` in `doc/`. --- doc/command/scion-pki/scion-pki_certificate_renew.rst | 4 ++-- doc/command/scion/scion_address.rst | 4 ++-- doc/command/scion/scion_ping.rst | 4 ++-- doc/command/scion/scion_showpaths.rst | 8 ++++---- doc/command/scion/scion_traceroute.rst | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/command/scion-pki/scion-pki_certificate_renew.rst b/doc/command/scion-pki/scion-pki_certificate_renew.rst index e834c9f27..1e06435d5 100755 --- a/doc/command/scion-pki/scion-pki_certificate_renew.rst +++ b/doc/command/scion-pki/scion-pki_certificate_renew.rst @@ -127,7 +127,7 @@ Options -h, --help help for renew -i, --interactive interactive mode --isd-as isd-as The local ISD-AS to use. (default 0-0) - -l, --local ip Local IP address to listen on. (default zero IP) + -l, --local ip Local IP address to listen on. (default invalid IP) --log.level string Console logging level verbosity (debug|info|error) --no-color disable colored output --no-probe do not probe paths for health @@ -141,7 +141,7 @@ 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 Deamon address. (default "127.0.0.1:30255") + --sciond string SCION Daemon address. (default "127.0.0.1:30255") --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) diff --git a/doc/command/scion/scion_address.rst b/doc/command/scion/scion_address.rst index d5afd61ed..54504ff29 100755 --- a/doc/command/scion/scion_address.rst +++ b/doc/command/scion/scion_address.rst @@ -39,8 +39,8 @@ 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 zero IP) - --sciond string SCION Deamon address. (default "127.0.0.1:30255") + -l, --local ip Local IP address to listen on. (default invalid IP) + --sciond string SCION Daemon address. (default "127.0.0.1:30255") SEE ALSO ~~~~~~~~ diff --git a/doc/command/scion/scion_ping.rst b/doc/command/scion/scion_ping.rst index f39f0bbf9..2c4943c21 100755 --- a/doc/command/scion/scion_ping.rst +++ b/doc/command/scion/scion_ping.rst @@ -95,7 +95,7 @@ Options -i, --interactive interactive mode --interval duration time between packets (default 1s) --isd-as isd-as The local ISD-AS to use. (default 0-0) - -l, --local ip Local IP address to listen on. (default zero IP) + -l, --local ip Local IP address to listen on. (default invalid IP) --log.level string Console logging level verbosity (debug|info|error) --max-mtu choose the payload size such that the sent SCION packet including the SCION Header, SCMP echo header and payload are equal to the MTU of the path. This flag overrides the @@ -108,7 +108,7 @@ 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 Deamon address. (default "127.0.0.1:30255") + --sciond string SCION Daemon address. (default "127.0.0.1:30255") --sequence string Space separated list of hop predicates --timeout duration timeout per packet (default 1s) --tracing.agent string Tracing agent address diff --git a/doc/command/scion/scion_showpaths.rst b/doc/command/scion/scion_showpaths.rst index fd7b5c32c..455d984e4 100755 --- a/doc/command/scion/scion_showpaths.rst +++ b/doc/command/scion/scion_showpaths.rst @@ -14,7 +14,7 @@ Synopsis 'showpaths' lists available paths between the local and the specified SCION ASe a. -By default, the paths are probed. Paths served from the SCION Deamon's might not +By default, the paths are probed. Paths served from the SCION Daemon's might not forward traffic successfully (e.g. if a network link went down, or there is a black hole on the path). To disable path probing, set the appropriate flag. @@ -96,13 +96,13 @@ Options --format string Specify the output format (human|json|yaml) (default "human") -h, --help help for showpaths --isd-as isd-as The local ISD-AS to use. (default 0-0) - -l, --local ip Local IP address to listen on. (default zero IP) + -l, --local ip Local IP address to listen on. (default invalid IP) --log.level string Console logging level verbosity (debug|info|error) -m, --maxpaths int Maximum number of paths that are displayed (default 10) --no-color disable colored output --no-probe Do not probe the paths and print the health status - -r, --refresh Set refresh flag for SCION Deamon path request - --sciond string SCION Deamon address. (default "127.0.0.1:30255") + -r, --refresh Set refresh flag for SCION Daemon path request + --sciond string SCION Daemon address. (default "127.0.0.1:30255") --sequence string Space separated list of hop predicates --timeout duration Timeout (default 5s) --tracing.agent string Tracing agent address diff --git a/doc/command/scion/scion_traceroute.rst b/doc/command/scion/scion_traceroute.rst index f36e8e764..fe60dddca 100755 --- a/doc/command/scion/scion_traceroute.rst +++ b/doc/command/scion/scion_traceroute.rst @@ -85,11 +85,11 @@ Options -h, --help help for traceroute -i, --interactive interactive mode --isd-as isd-as The local ISD-AS to use. (default 0-0) - -l, --local ip Local IP address to listen on. (default zero IP) + -l, --local ip Local IP address to listen on. (default invalid IP) --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 Deamon address. (default "127.0.0.1:30255") + --sciond string SCION Daemon address. (default "127.0.0.1:30255") --sequence string Space separated list of hop predicates --timeout duration timeout per packet (default 1s) --tracing.agent string Tracing agent address From 595839f08d2a9570d767845da4c08e11755e2aaa Mon Sep 17 00:00:00 2001 From: HawkCorrigan Date: Sun, 2 Jul 2023 21:48:10 +0200 Subject: [PATCH 033/255] doc: fix link to EPIC-HP design doc (#4358) Change link to point to the proper EPIC-HP design doc PR instead of a PR for COLIBRI design document. --- doc/dev/design/EPIC.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dev/design/EPIC.md b/doc/dev/design/EPIC.md index e879f701b..4e69bd503 100644 --- a/doc/dev/design/EPIC.md +++ b/doc/dev/design/EPIC.md @@ -3,7 +3,7 @@ - Author: Marc Wyss, Markus Legner - Last updated: 2020-10-14 - Status: **implemented** -- Discussion at: [#3884](https://github.com/scionproto/scion/issues/3653) +- Discussion at: [#3884](https://github.com/scionproto/scion/issues/3884) - Implemented in: [#3951](https://github.com/scionproto/scion/issues/3951), [#3954](https://github.com/scionproto/scion/issues/3954), [#4079](https://github.com/scionproto/scion/issues/4079) From 10fc34bc8ca4a66d7a524ab024086f21a07ff995 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Thu, 6 Jul 2023 09:09:36 +0200 Subject: [PATCH 034/255] doc: update issue template (#4359) --- .github/ISSUE_TEMPLATE/01-proposal.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/01-proposal.md b/.github/ISSUE_TEMPLATE/01-proposal.md index 77c7b316e..0a538d914 100644 --- a/.github/ISSUE_TEMPLATE/01-proposal.md +++ b/.github/ISSUE_TEMPLATE/01-proposal.md @@ -6,6 +6,6 @@ labels: i/proposal From 9f77b13ed8b36273de21f72d01d67bb0cd301e4e Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Mon, 10 Jul 2023 14:02:55 +0200 Subject: [PATCH 035/255] refactor: replace addr.HostAddr hierarchy with tagged union addr.Host (#4346) Replace the `addr.HostAddr` type hierarchy, consisting of the `HostAddr` interface and the `HostNone`, `HostIPv4`, `HostIPv6` and `HostSVC` implementations with a single type `addr.Host`, representing all the different host address types as a tagged union ("sum type"). This uses, and follows the spirit of, the `net/netip.Addr` types to represent IP addresses for both IPv4 and IPv6. The `addr.Host` type is a simple value type, which can be created and copied without heap allocations and can be used in comparisons and as map keys. In addition to replacing all uses of `addr.HostAddr`, the new `addr.Host` type is used in the `slayers.SCION.Get/SetSrc/DstAddr` interfaces, as well as in the DRKey infrastructure. Using a consistent representation of the addresses allows to get rid of duplicate functionality and a number of address conversions, e.g. in `snet`. In contrast to the `addr.HostAddr` interface, the new `addr.Host` does not implement the `net.Addr` interface. In particular, service addresses were passed through layers requiring a `net.Addr`. Use `snet.SVCAddr` in these cases. Additionally, add a new `addr.Addr` type representing a full SCION address (ISD, AS and host address), including parsing functionality. This definition is identical to the `snet.SCIONAddress` type, which is now only kept as a type alias for compatibility. Future work: - `pkg/addr` is a public API and should have a more SCION-specific and less clash-likely name, e.g. `saddr` - replace `snet.SCIONAddress` by `addr.Addr` - adopt using `addr.Addr` in the ping, traceroute etc tools, in place of the ill-fitting use of `snet.UDPAddr`. - add `addr.MustParse{ISD,AS,IA}` for completeness sake (currently in xtest package) - get rid of the IP-slice to `netip.Addr` conversions by gradually increasing the adoption of `netip.Addr` and related APIs --- control/beaconing/writer.go | 2 +- control/config/BUILD.bazel | 1 - control/config/drkey.go | 3 +- control/drkey/grpc/drkey_service.go | 12 +- control/onehop/addr.go | 2 +- control/segreq/helpers.go | 2 +- daemon/cmd/daemon/main.go | 2 +- daemon/drkey/grpc/BUILD.bazel | 1 + daemon/drkey/grpc/fetcher.go | 7 +- daemon/fetcher/fetcher.go | 2 +- dispatcher/cmd/dispatcher/main_test.go | 78 ++-- dispatcher/dispatcher.go | 4 +- .../internal/registration/bench_test.go | 4 +- .../internal/registration/generators_test.go | 2 +- dispatcher/internal/registration/iatable.go | 14 +- dispatcher/internal/registration/svctable.go | 22 +- .../internal/registration/svctable_test.go | 8 +- dispatcher/internal/registration/table.go | 6 +- .../internal/registration/table_test.go | 2 +- dispatcher/internal/respool/BUILD.bazel | 1 + dispatcher/internal/respool/packet_test.go | 6 +- dispatcher/network/app_socket.go | 2 +- dispatcher/table.go | 2 +- dispatcher/underlay.go | 19 +- dispatcher/underlay_test.go | 32 +- gateway/cmd/gateway/main.go | 7 +- gateway/gateway.go | 6 +- gateway/pathhealth/pathwatcher.go | 7 +- pkg/addr/BUILD.bazel | 9 +- pkg/addr/addr.go | 117 ++++++ pkg/addr/addr_test.go | 221 +++++++++++ pkg/addr/doc.go | 3 + pkg/addr/host.go | 357 ++++-------------- pkg/addr/host_test.go | 192 +++++++--- pkg/addr/svc.go | 106 ++++++ pkg/addr/svc_test.go | 78 ++++ pkg/daemon/apitypes.go | 6 +- pkg/daemon/daemon.go | 2 +- pkg/daemon/grpc.go | 8 +- pkg/daemon/mock_daemon/mock.go | 4 +- pkg/drkey/generic/BUILD.bazel | 2 + pkg/drkey/generic/generic.go | 46 ++- pkg/drkey/protocol.go | 64 +--- pkg/drkey/specific/BUILD.bazel | 1 + pkg/drkey/specific/specific.go | 45 ++- pkg/experimental/epic/BUILD.bazel | 1 + pkg/experimental/epic/epic_test.go | 5 +- .../hiddenpath/beaconwriter_test.go | 2 +- pkg/grpc/BUILD.bazel | 1 + pkg/grpc/dialer.go | 9 +- pkg/grpc/dialer_test.go | 23 +- pkg/slayers/export_test.go | 2 - pkg/slayers/scion.go | 72 ++-- pkg/slayers/scion_test.go | 64 ++-- pkg/slayers/scmp_test.go | 10 +- pkg/snet/addrutil/addrutil.go | 2 +- pkg/snet/base.go | 4 +- pkg/snet/dispatcher.go | 4 +- pkg/snet/interface.go | 4 +- pkg/snet/mock_snet/mock.go | 6 +- pkg/snet/packet.go | 50 +-- pkg/snet/packet_conn.go | 10 +- pkg/snet/packet_test.go | 45 ++- pkg/snet/reader.go | 6 +- pkg/snet/snet.go | 4 +- pkg/snet/svcaddr.go | 2 +- pkg/snet/svcaddr_test.go | 2 +- pkg/snet/udpaddr.go | 30 +- pkg/snet/writer.go | 16 +- pkg/sock/reliable/frame.go | 7 +- pkg/sock/reliable/mock_reliable/mock.go | 2 +- pkg/sock/reliable/packetizer.go | 5 +- pkg/sock/reliable/reconnect/network.go | 4 +- pkg/sock/reliable/registration.go | 8 +- pkg/sock/reliable/reliable.go | 8 +- pkg/sock/reliable/util.go | 42 ++- pkg/spao/BUILD.bazel | 1 - pkg/spao/mac_test.go | 3 +- private/app/appnet/addr.go | 6 +- private/app/appnet/addr_test.go | 2 +- private/app/appnet/export_test.go | 2 +- private/app/appnet/mock_infraenv/mock.go | 4 +- private/app/path/pathprobe/paths.go | 24 +- private/svc/resolver.go | 11 +- private/svc/resolver_test.go | 1 + private/svc/svc.go | 13 +- private/svc/svc_test.go | 15 +- private/topology/interface.go | 32 +- private/topology/mock_topology/mock.go | 12 +- private/topology/reload.go | 2 +- router/connector.go | 4 +- router/control/conf.go | 6 +- router/dataplane.go | 65 ++-- router/dataplane_test.go | 56 +-- router/export_test.go | 7 +- router/svc.go | 10 +- scion-pki/certs/renew.go | 12 +- scion/ping/util.go | 14 +- scion/showpaths/showpaths.go | 4 +- scion/traceroute/traceroute.go | 21 +- tools/braccept/cases/bfd.go | 16 +- tools/braccept/cases/child_to_child_xover.go | 5 +- tools/braccept/cases/child_to_internal.go | 13 +- tools/braccept/cases/child_to_parent.go | 5 +- tools/braccept/cases/internal_to_child.go | 13 +- tools/braccept/cases/jumbo.go | 5 +- tools/braccept/cases/onehop.go | 9 +- tools/braccept/cases/parent_to_child.go | 5 +- tools/braccept/cases/parent_to_internal.go | 9 +- tools/braccept/cases/scmp_dest_unreachable.go | 6 +- tools/braccept/cases/scmp_expired_hop.go | 35 +- tools/braccept/cases/scmp_invalid_hop.go | 13 +- tools/braccept/cases/scmp_invalid_ia.go | 25 +- tools/braccept/cases/scmp_invalid_mac.go | 13 +- tools/braccept/cases/scmp_invalid_pkt.go | 17 +- .../cases/scmp_invalid_segment_change.go | 25 +- .../scmp_invalid_segment_change_local.go | 19 +- tools/braccept/cases/scmp_traceroute.go | 43 +-- tools/braccept/cases/scmp_unknown_hop.go | 13 +- tools/braccept/cases/svc.go | 4 +- tools/braccept/runner/BUILD.bazel | 1 + tools/braccept/runner/compare_test.go | 6 +- tools/end2end/main.go | 14 +- tools/pktgen/cmd/pktgen/BUILD.bazel | 1 + tools/pktgen/cmd/pktgen/main.go | 22 +- 125 files changed, 1527 insertions(+), 1104 deletions(-) create mode 100644 pkg/addr/addr.go create mode 100644 pkg/addr/addr_test.go create mode 100644 pkg/addr/svc.go create mode 100644 pkg/addr/svc_test.go diff --git a/control/beaconing/writer.go b/control/beaconing/writer.go index 1c5b18cb0..70dcde0ea 100644 --- a/control/beaconing/writer.go +++ b/control/beaconing/writer.go @@ -37,7 +37,7 @@ import ( // Pather computes the remote address with a path based on the provided segment. type Pather interface { - GetPath(svc addr.HostSVC, ps *seg.PathSegment) (*snet.SVCAddr, error) + GetPath(svc addr.SVC, ps *seg.PathSegment) (*snet.SVCAddr, error) } // SegmentProvider provides segments to register for the specified type. diff --git a/control/config/BUILD.bazel b/control/config/BUILD.bazel index 97e2c636e..82c227655 100644 --- a/control/config/BUILD.bazel +++ b/control/config/BUILD.bazel @@ -11,7 +11,6 @@ go_library( importpath = "github.com/scionproto/scion/control/config", visibility = ["//visibility:public"], deps = [ - "//pkg/addr:go_default_library", "//pkg/drkey:go_default_library", "//pkg/log:go_default_library", "//pkg/private/serrors:go_default_library", diff --git a/control/config/drkey.go b/control/config/drkey.go index 38ad9f776..27df174c2 100644 --- a/control/config/drkey.go +++ b/control/config/drkey.go @@ -20,7 +20,6 @@ import ( "strings" "time" - "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/private/config" @@ -118,7 +117,7 @@ func (cfg *SecretValueHostList) Validate() error { return serrors.New("GENERIC protocol is not allowed") } for _, ip := range list { - if h := addr.HostFromIPStr(ip); h == nil { + if _, err := netip.ParseAddr(ip); err != nil { return serrors.New("Syntax error: not a valid address", "ip", ip) } } diff --git a/control/drkey/grpc/drkey_service.go b/control/drkey/grpc/drkey_service.go index b0a7278c2..23434a391 100644 --- a/control/drkey/grpc/drkey_service.go +++ b/control/drkey/grpc/drkey_service.go @@ -299,7 +299,7 @@ func validateASHostReq(meta drkey.ASHostMeta, localIA addr.IA, peerAddr net.Addr return serrors.New("invalid request, req.dstIA != localIA", "request_dst_isd_as", meta.DstIA, "local_isd_as", localIA) } - dstHost := addr.HostFromIPStr(meta.DstHost) + dstHost := net.ParseIP(meta.DstHost) if !hostAddr.Equal(dstHost) { return serrors.New("invalid request, dst_host != remote host", "dst_host", dstHost, "remote_host", hostAddr) @@ -320,7 +320,7 @@ func validateHostASReq(meta drkey.HostASMeta, localIA addr.IA, peerAddr net.Addr return serrors.New("invalid request, req.SrcIA != localIA", "request_src_isd_as", meta.SrcIA, "local_isd_as", localIA) } - srcHost := addr.HostFromIPStr(meta.SrcHost) + srcHost := net.ParseIP(meta.SrcHost) if !hostAddr.Equal(srcHost) { return serrors.New("invalid request, src_host != remote host", "src_host", srcHost, "remote_host", hostAddr) @@ -335,8 +335,8 @@ func validateHostHostReq(meta drkey.HostHostMeta, localIA addr.IA, peerAddr net. if err != nil { return err } - srcHost := addr.HostFromIPStr(meta.SrcHost) - dstHost := addr.HostFromIPStr(meta.DstHost) + srcHost := net.ParseIP(meta.SrcHost) + dstHost := net.ParseIP(meta.DstHost) if !((meta.SrcIA.Equal(localIA) && hostAddr.Equal(srcHost)) || (meta.DstIA.Equal(localIA) && hostAddr.Equal(dstHost))) { @@ -353,13 +353,13 @@ func validateHostHostReq(meta drkey.HostHostMeta, localIA addr.IA, peerAddr net. return nil } -func hostAddrFromPeer(peerAddr net.Addr) (addr.HostAddr, error) { +func hostAddrFromPeer(peerAddr net.Addr) (net.IP, error) { tcpAddr, ok := peerAddr.(*net.TCPAddr) if !ok { return nil, serrors.New("invalid peer address type, expected *net.TCPAddr", "peer", peerAddr, "type", common.TypeOf(peerAddr)) } - return addr.HostFromIP(tcpAddr.IP), nil + return tcpAddr.IP, nil } func getMeta(protoId drkeypb.Protocol, ts *timestamppb.Timestamp, srcIA, diff --git a/control/onehop/addr.go b/control/onehop/addr.go index d02fb54c7..6202443da 100644 --- a/control/onehop/addr.go +++ b/control/onehop/addr.go @@ -35,7 +35,7 @@ type Addr struct { // Egress is the interface over which the remote AS should be reached. Egress uint16 // SVC is the service anycast address of the designated service in the remote AS. - SVC addr.HostSVC + SVC addr.SVC // NextHop is the router that owns the egress interface. NextHop *net.UDPAddr } diff --git a/control/segreq/helpers.go b/control/segreq/helpers.go index f7a517b74..391f243c7 100644 --- a/control/segreq/helpers.go +++ b/control/segreq/helpers.go @@ -30,7 +30,7 @@ import ( // Pather computes the remote address with a path based on the provided segment. type Pather interface { - GetPath(svc addr.HostSVC, ps *seg.PathSegment) (*snet.SVCAddr, error) + GetPath(svc addr.SVC, ps *seg.PathSegment) (*snet.SVCAddr, error) } // CoreChecker checks whether a given ia is core. diff --git a/daemon/cmd/daemon/main.go b/daemon/cmd/daemon/main.go index d663f9af8..a8ec8ca52 100644 --- a/daemon/cmd/daemon/main.go +++ b/daemon/cmd/daemon/main.go @@ -121,7 +121,7 @@ func realMain(ctx context.Context) error { defer rcCleaner.Stop() dialer := &libgrpc.TCPDialer{ - SvcResolver: func(dst addr.HostSVC) []resolver.Address { + SvcResolver: func(dst addr.SVC) []resolver.Address { if base := dst.Base(); base != addr.SvcCS { panic("Unsupported address type, implementation error?") } diff --git a/daemon/drkey/grpc/BUILD.bazel b/daemon/drkey/grpc/BUILD.bazel index 26801aaa0..c1fdb982c 100644 --- a/daemon/drkey/grpc/BUILD.bazel +++ b/daemon/drkey/grpc/BUILD.bazel @@ -16,6 +16,7 @@ go_library( "//pkg/proto/control_plane:go_default_library", "//pkg/proto/drkey:go_default_library", "//pkg/scrypto/cppki:go_default_library", + "//pkg/snet:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", ], ) diff --git a/daemon/drkey/grpc/fetcher.go b/daemon/drkey/grpc/fetcher.go index 491687179..a6e51ffe7 100644 --- a/daemon/drkey/grpc/fetcher.go +++ b/daemon/drkey/grpc/fetcher.go @@ -22,6 +22,7 @@ import ( sc_grpc "github.com/scionproto/scion/pkg/grpc" "github.com/scionproto/scion/pkg/private/serrors" cppb "github.com/scionproto/scion/pkg/proto/control_plane" + "github.com/scionproto/scion/pkg/snet" ) // Fetcher obtains end-host key from the local CS. @@ -34,7 +35,7 @@ func (f *Fetcher) ASHostKey( meta drkey.ASHostMeta, ) (drkey.ASHostKey, error) { - conn, err := f.Dialer.Dial(ctx, addr.SvcCS) + conn, err := f.Dialer.Dial(ctx, &snet.SVCAddr{SVC: addr.SvcCS}) if err != nil { return drkey.ASHostKey{}, serrors.WrapStr("dialing", err) } @@ -59,7 +60,7 @@ func (f *Fetcher) HostASKey( meta drkey.HostASMeta, ) (drkey.HostASKey, error) { - conn, err := f.Dialer.Dial(ctx, addr.SvcCS) + conn, err := f.Dialer.Dial(ctx, &snet.SVCAddr{SVC: addr.SvcCS}) if err != nil { return drkey.HostASKey{}, serrors.WrapStr("dialing", err) } @@ -84,7 +85,7 @@ func (f *Fetcher) HostHostKey( meta drkey.HostHostMeta, ) (drkey.HostHostKey, error) { - conn, err := f.Dialer.Dial(ctx, addr.SvcCS) + conn, err := f.Dialer.Dial(ctx, &snet.SVCAddr{SVC: addr.SvcCS}) if err != nil { return drkey.HostHostKey{}, serrors.WrapStr("dialing", err) } diff --git a/daemon/fetcher/fetcher.go b/daemon/fetcher/fetcher.go index 743fd93bb..63206b099 100644 --- a/daemon/fetcher/fetcher.go +++ b/daemon/fetcher/fetcher.go @@ -126,7 +126,7 @@ type dstProvider struct { } func (r *dstProvider) Dst(_ context.Context, _ segfetcher.Request) (net.Addr, error) { - return addr.SvcCS, nil + return &snet.SVCAddr{SVC: addr.SvcCS}, nil } type neverLocal struct{} diff --git a/dispatcher/cmd/dispatcher/main_test.go b/dispatcher/cmd/dispatcher/main_test.go index d3c4023d6..86e3dc710 100644 --- a/dispatcher/cmd/dispatcher/main_test.go +++ b/dispatcher/cmd/dispatcher/main_test.go @@ -19,6 +19,7 @@ import ( "context" "fmt" "net" + "net/netip" "os" "path/filepath" "testing" @@ -65,11 +66,10 @@ func getSocketName(dir string) (string, error) { type ClientAddress struct { IA addr.IA - PublicAddress addr.HostAddr + PublicAddress netip.Addr PublicPort uint16 - ServiceAddress addr.HostSVC + ServiceAddress addr.SVC UnderlayAddress *net.UDPAddr - UnderlayPort uint16 } type TestCase struct { @@ -84,7 +84,7 @@ func genTestCases(dispatcherPort int) []*TestCase { // Addressing information var ( commonIA = xtest.MustParseIA("1-ff00:0:1") - commonPublicL3Address = addr.HostFromIP(net.IP{127, 0, 0, 1}) + commonPublicL3Address = netip.AddrFrom4([4]byte{127, 0, 0, 1}) commonUnderlayAddress = &net.UDPAddr{IP: net.IP{127, 0, 0, 1}, Port: dispatcherPort} clientXAddress = &ClientAddress{ IA: commonIA, @@ -111,11 +111,11 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.UDPPayload{ SrcPort: clientXAddress.PublicPort, @@ -131,11 +131,11 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.UDPPayload{ SrcPort: clientXAddress.PublicPort, @@ -154,11 +154,11 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientYAddress.IA, - Host: clientYAddress.PublicAddress, + Host: addr.HostIP(clientYAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientYAddress.IA, - Host: clientYAddress.ServiceAddress, + Host: addr.HostSVC(clientYAddress.ServiceAddress), }, Payload: snet.UDPPayload{ SrcPort: clientYAddress.PublicPort, @@ -174,11 +174,11 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientYAddress.IA, - Host: clientYAddress.PublicAddress, + Host: addr.HostIP(clientYAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientYAddress.IA, - Host: clientYAddress.ServiceAddress, + Host: addr.HostSVC(clientYAddress.ServiceAddress), }, Payload: snet.UDPPayload{ SrcPort: clientYAddress.PublicPort, @@ -198,22 +198,22 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.SCMPDestinationUnreachable{ Payload: MustPack(snet.Packet{ PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.UDPPayload{SrcPort: clientXAddress.PublicPort}, Path: path.Empty{}, @@ -228,22 +228,22 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.SCMPDestinationUnreachable{ Payload: MustPack(snet.Packet{ PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.UDPPayload{SrcPort: clientXAddress.PublicPort}, Path: path.Empty{}, @@ -265,11 +265,11 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:42"), // middle of nowhere - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientYAddress.IA, - Host: clientYAddress.PublicAddress, + Host: addr.HostIP(clientYAddress.PublicAddress), }, Payload: snet.SCMPEchoRequest{Identifier: 0xdead}, Path: path.Empty{}, @@ -279,22 +279,22 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.SCMPDestinationUnreachable{ Payload: MustPack(snet.Packet{ PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.SCMPEchoRequest{Identifier: 0xdead}, Path: path.Empty{}, @@ -309,22 +309,22 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.SCMPDestinationUnreachable{ Payload: MustPack(snet.Packet{ PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.SCMPEchoRequest{Identifier: 0xdead}, Path: path.Empty{}, @@ -344,11 +344,11 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientYAddress.IA, - Host: clientYAddress.PublicAddress, + Host: addr.HostIP(clientYAddress.PublicAddress), }, Payload: snet.SCMPEchoRequest{ Identifier: 0xdead, @@ -363,11 +363,11 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientYAddress.IA, - Host: clientYAddress.PublicAddress, + Host: addr.HostIP(clientYAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.SCMPEchoReply{ Identifier: 0xdead, @@ -387,11 +387,11 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientYAddress.IA, - Host: clientYAddress.PublicAddress, + Host: addr.HostIP(clientYAddress.PublicAddress), }, Payload: snet.SCMPTracerouteRequest{Identifier: 0xdeaf, Sequence: 0xcafd}, Path: path.Empty{}, @@ -402,11 +402,11 @@ func genTestCases(dispatcherPort int) []*TestCase { PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: clientYAddress.IA, - Host: clientYAddress.PublicAddress, + Host: addr.HostIP(clientYAddress.PublicAddress), }, Destination: snet.SCIONAddress{ IA: clientXAddress.IA, - Host: clientXAddress.PublicAddress, + Host: addr.HostIP(clientXAddress.PublicAddress), }, Payload: snet.SCMPTracerouteReply{Identifier: 0xdeaf, Sequence: 0xcafd}, Path: snet.RawPath{}, @@ -445,7 +445,7 @@ func RunTestCase(t *testing.T, tc *TestCase, settings *TestSettings) { ctx, tc.ClientAddress.IA, &net.UDPAddr{ - IP: tc.ClientAddress.PublicAddress.IP(), + IP: tc.ClientAddress.PublicAddress.AsSlice(), Port: int(tc.ClientAddress.PublicPort), }, tc.ClientAddress.ServiceAddress, diff --git a/dispatcher/dispatcher.go b/dispatcher/dispatcher.go index f38bf52d8..86d15a09d 100644 --- a/dispatcher/dispatcher.go +++ b/dispatcher/dispatcher.go @@ -94,7 +94,7 @@ func (as *Server) Serve() error { // Register creates a new connection. func (as *Server) Register(ctx context.Context, ia addr.IA, address *net.UDPAddr, - svc addr.HostSVC) (net.PacketConn, uint16, error) { + svc addr.SVC) (net.PacketConn, uint16, error) { tableEntry := newTableEntry() ref, err := as.routingTable.Register(ia, address, nil, svc, tableEntry) @@ -178,7 +178,7 @@ func (ac *Conn) LocalAddr() net.Addr { return ac.regReference.UDPAddr() } -func (ac *Conn) SVCAddr() addr.HostSVC { +func (ac *Conn) SVCAddr() addr.SVC { return ac.regReference.SVCAddr() } diff --git a/dispatcher/internal/registration/bench_test.go b/dispatcher/internal/registration/bench_test.go index 84d5e3190..177791c6a 100644 --- a/dispatcher/internal/registration/bench_test.go +++ b/dispatcher/internal/registration/bench_test.go @@ -25,7 +25,7 @@ type registerArgs struct { ia addr.IA public *net.UDPAddr bind net.IP - svc addr.HostSVC + svc addr.SVC value interface{} } @@ -78,7 +78,7 @@ func BenchmarkLookupPublicIPv4(b *testing.B) { } type lookupServiceArgs struct { - svc addr.HostSVC + svc addr.SVC bind net.IP } diff --git a/dispatcher/internal/registration/generators_test.go b/dispatcher/internal/registration/generators_test.go index 35eeb8a6b..ce12a84c0 100644 --- a/dispatcher/internal/registration/generators_test.go +++ b/dispatcher/internal/registration/generators_test.go @@ -49,7 +49,7 @@ func getRandomIA() addr.IA { ) } -func getRandomSVC() addr.HostSVC { +func getRandomSVC() addr.SVC { switch rand.Intn(2) { case 0: return addr.SvcNone diff --git a/dispatcher/internal/registration/iatable.go b/dispatcher/internal/registration/iatable.go index a19c2a937..b677d09d3 100644 --- a/dispatcher/internal/registration/iatable.go +++ b/dispatcher/internal/registration/iatable.go @@ -39,7 +39,7 @@ type RegReference interface { UDPAddr() *net.UDPAddr // SVCAddr returns the SVC address associated with this reference. If no // SVC address is associated, it returns SvcNone. - SVCAddr() addr.HostSVC + SVCAddr() addr.SVC // RegisterID attaches an SCMP ID to this reference. The ID is released // when the reference is freed. Registering another ID does not overwrite // the previous; instead, multiple IDs get associated with the reference. @@ -69,7 +69,7 @@ type IATable interface { // see the documentation for SVCTable. // // To unregister from the table, free the returned reference. - Register(ia addr.IA, public *net.UDPAddr, bind net.IP, svc addr.HostSVC, + Register(ia addr.IA, public *net.UDPAddr, bind net.IP, svc addr.SVC, value interface{}) (RegReference, error) // LookupPublic returns the value associated with the selected public // address. Wildcard addresses are supported. If an entry is found, the @@ -87,7 +87,7 @@ type IATable interface { // // If SVC is a multicast address, more than one entry can be returned. The // bind address is ignored in this case. - LookupService(ia addr.IA, svc addr.HostSVC, bind net.IP) []interface{} + LookupService(ia addr.IA, svc addr.SVC, bind net.IP) []interface{} // LookupID returns the entry associated with the SCMP General class ID id. // The ID is used for SCMP Echo, TraceRoute, and RecordPath functionality. // If an entry is found, the returned boolean is set to true. Otherwise, it @@ -122,7 +122,7 @@ func newIATable(minPort, maxPort int) *iaTable { } } -func (t *iaTable) Register(ia addr.IA, public *net.UDPAddr, bind net.IP, svc addr.HostSVC, +func (t *iaTable) Register(ia addr.IA, public *net.UDPAddr, bind net.IP, svc addr.SVC, value interface{}) (RegReference, error) { t.mtx.Lock() @@ -160,7 +160,7 @@ func (t *iaTable) LookupPublic(ia addr.IA, public *net.UDPAddr) (interface{}, bo return nil, false } -func (t *iaTable) LookupService(ia addr.IA, svc addr.HostSVC, bind net.IP) []interface{} { +func (t *iaTable) LookupService(ia addr.IA, svc addr.SVC, bind net.IP) []interface{} { t.mtx.RLock() defer t.mtx.RUnlock() if table, ok := t.ia[ia]; ok { @@ -184,7 +184,7 @@ type iaTableReference struct { table *iaTable ia addr.IA entryRef *TableReference - svc addr.HostSVC + svc addr.SVC // value is the main table information associated with this reference value interface{} } @@ -202,7 +202,7 @@ func (r *iaTableReference) UDPAddr() *net.UDPAddr { return r.entryRef.UDPAddr() } -func (r *iaTableReference) SVCAddr() addr.HostSVC { +func (r *iaTableReference) SVCAddr() addr.SVC { return r.svc } diff --git a/dispatcher/internal/registration/svctable.go b/dispatcher/internal/registration/svctable.go index 6aacfe0c1..7c93f41bd 100644 --- a/dispatcher/internal/registration/svctable.go +++ b/dispatcher/internal/registration/svctable.go @@ -61,7 +61,7 @@ type SVCTable interface { // // To clean up resources, call Free on the returned Reference. Calling Free // more than once will cause a panic. - Register(svc addr.HostSVC, address *net.UDPAddr, value interface{}) (Reference, error) + Register(svc addr.SVC, address *net.UDPAddr, value interface{}) (Reference, error) // Lookup returns the entries associated with svc and ip. // // If SVC is an anycast address, at most one entry is returned. The ip @@ -73,7 +73,7 @@ type SVCTable interface { // // If SVC is a multicast address, more than one entry can be returned. The // ip address is ignored in this case. - Lookup(svc addr.HostSVC, ip net.IP) []interface{} + Lookup(svc addr.SVC, ip net.IP) []interface{} String() string } @@ -84,16 +84,16 @@ func NewSVCTable() SVCTable { var _ SVCTable = (*svcTable)(nil) type svcTable struct { - m map[addr.HostSVC]unicastIpTable + m map[addr.SVC]unicastIpTable } func newSvcTable() *svcTable { return &svcTable{ - m: make(map[addr.HostSVC]unicastIpTable), + m: make(map[addr.SVC]unicastIpTable), } } -func (t *svcTable) Register(svc addr.HostSVC, address *net.UDPAddr, +func (t *svcTable) Register(svc addr.SVC, address *net.UDPAddr, value interface{}) (Reference, error) { if err := validateUDPAddr(address); err != nil { @@ -126,7 +126,7 @@ func (t *svcTable) Register(svc addr.HostSVC, address *net.UDPAddr, return t.registerOne(svc, address, value) } -func (t *svcTable) registerOne(svc addr.HostSVC, address *net.UDPAddr, +func (t *svcTable) registerOne(svc addr.SVC, address *net.UDPAddr, value interface{}) (Reference, error) { if _, ok := t.m[svc]; !ok { t.m[svc] = make(unicastIpTable) @@ -141,7 +141,7 @@ func (t *svcTable) registerOne(svc addr.HostSVC, address *net.UDPAddr, }, nil } -func (t *svcTable) Lookup(svc addr.HostSVC, ip net.IP) []interface{} { +func (t *svcTable) Lookup(svc addr.SVC, ip net.IP) []interface{} { var values []interface{} if svc.IsMulticast() { values = t.multicast(svc) @@ -153,7 +153,7 @@ func (t *svcTable) Lookup(svc addr.HostSVC, ip net.IP) []interface{} { return values } -func (t *svcTable) multicast(svc addr.HostSVC) []interface{} { +func (t *svcTable) multicast(svc addr.SVC) []interface{} { var values []interface{} ipTable, ok := t.m[svc.Base()] if !ok { @@ -167,7 +167,7 @@ func (t *svcTable) multicast(svc addr.HostSVC) []interface{} { return values } -func (t *svcTable) anycast(svc addr.HostSVC, ip net.IP) (interface{}, bool) { +func (t *svcTable) anycast(svc addr.SVC, ip net.IP) (interface{}, bool) { ipTable, ok := t.m[svc] if !ok { return nil, false @@ -192,13 +192,13 @@ func (t *svcTable) String() string { return fmt.Sprintf("%v", t.m) } -func (t *svcTable) buildCleanupCallback(svc addr.HostSVC, ip net.IP, port *ring.Ring) func() { +func (t *svcTable) buildCleanupCallback(svc addr.SVC, ip net.IP, port *ring.Ring) func() { return func() { t.doCleanup(svc, ip, port) } } -func (t *svcTable) doCleanup(svc addr.HostSVC, ip net.IP, port *ring.Ring) { +func (t *svcTable) doCleanup(svc addr.SVC, ip net.IP, port *ring.Ring) { ipTable := t.m[svc] portList := ipTable[ip.String()] portList.Remove(port) diff --git a/dispatcher/internal/registration/svctable_test.go b/dispatcher/internal/registration/svctable_test.go index 240a7ebe1..f89e0c1a2 100644 --- a/dispatcher/internal/registration/svctable_test.go +++ b/dispatcher/internal/registration/svctable_test.go @@ -32,7 +32,7 @@ func TestSVCTableLookup(t *testing.T) { value := "test value" testCases := map[string]struct { - Svc addr.HostSVC + Svc addr.SVC IP net.IP Prepare func(t *testing.T, table SVCTable) Expected []interface{} @@ -122,7 +122,7 @@ func TestSVCTableRegistration(t *testing.T) { testCases := map[string]struct { Prepare func(t *testing.T, table SVCTable) // Input Register - Svc addr.HostSVC + Svc addr.SVC Addr *net.UDPAddr Value interface{} // Assertions @@ -401,7 +401,7 @@ func TestSVCTableWildcard(t *testing.T) { defer reference.Free() testCases := map[string]struct { - Address addr.HostSVC + Address addr.SVC LookupResultCount int }{ "cs": { @@ -442,7 +442,7 @@ func TestSVCTableWildcardRollback(t *testing.T) { table := NewSVCTable() testCases := map[string]struct { - RegisteredAddress addr.HostSVC + RegisteredAddress addr.SVC LookupResultCSCount int LookupResultDSCount int }{ diff --git a/dispatcher/internal/registration/table.go b/dispatcher/internal/registration/table.go index 451d14518..278cbc892 100644 --- a/dispatcher/internal/registration/table.go +++ b/dispatcher/internal/registration/table.go @@ -44,7 +44,7 @@ func NewTable(minPort, maxPort int) *Table { } } -func (t *Table) Register(public *net.UDPAddr, bind net.IP, svc addr.HostSVC, +func (t *Table) Register(public *net.UDPAddr, bind net.IP, svc addr.SVC, value interface{}) (*TableReference, error) { if public == nil { @@ -69,7 +69,7 @@ func (t *Table) Register(public *net.UDPAddr, bind net.IP, svc addr.HostSVC, return &TableReference{table: t, address: address, svcRef: svcRef}, nil } -func (t *Table) insertSVCIfRequested(svc addr.HostSVC, bind net.IP, port int, +func (t *Table) insertSVCIfRequested(svc addr.SVC, bind net.IP, port int, value interface{}) (Reference, error) { if svc != addr.SvcNone { @@ -86,7 +86,7 @@ func (t *Table) LookupPublic(address *net.UDPAddr) (interface{}, bool) { return t.udpPortTable.Lookup(address) } -func (t *Table) LookupService(svc addr.HostSVC, bind net.IP) []interface{} { +func (t *Table) LookupService(svc addr.SVC, bind net.IP) []interface{} { return t.svcTable.Lookup(svc, bind) } diff --git a/dispatcher/internal/registration/table_test.go b/dispatcher/internal/registration/table_test.go index 5d717035b..000c06848 100644 --- a/dispatcher/internal/registration/table_test.go +++ b/dispatcher/internal/registration/table_test.go @@ -30,7 +30,7 @@ func TestRegister(t *testing.T) { tests := map[string]struct { a *net.UDPAddr b net.IP - svc addr.HostSVC + svc addr.SVC af assert.ErrorAssertionFunc }{ "no public address fails": { diff --git a/dispatcher/internal/respool/BUILD.bazel b/dispatcher/internal/respool/BUILD.bazel index ba4207764..f66f9fa63 100644 --- a/dispatcher/internal/respool/BUILD.bazel +++ b/dispatcher/internal/respool/BUILD.bazel @@ -22,6 +22,7 @@ go_test( srcs = ["packet_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/addr:go_default_library", "//pkg/private/xtest:go_default_library", "//pkg/slayers:go_default_library", "//pkg/slayers/path:go_default_library", diff --git a/dispatcher/internal/respool/packet_test.go b/dispatcher/internal/respool/packet_test.go index c2843d7ea..f3ad215bb 100644 --- a/dispatcher/internal/respool/packet_test.go +++ b/dispatcher/internal/respool/packet_test.go @@ -15,13 +15,13 @@ package respool import ( - "net" "testing" "github.com/google/gopacket" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path" @@ -131,7 +131,7 @@ func scionLayer(t *testing.T, l4 slayers.L4ProtocolType) *slayers.SCION { }, }, } - require.NoError(t, scion.SetSrcAddr(&net.IPAddr{IP: net.IP{127, 0, 0, 1}})) - require.NoError(t, scion.SetDstAddr(&net.IPAddr{IP: net.IP{127, 0, 0, 2}})) + require.NoError(t, scion.SetSrcAddr(addr.MustParseHost("127.0.0.1"))) + require.NoError(t, scion.SetDstAddr(addr.MustParseHost("127.0.0.2"))) return scion } diff --git a/dispatcher/network/app_socket.go b/dispatcher/network/app_socket.go index 300cf7f19..2a6167de8 100644 --- a/dispatcher/network/app_socket.go +++ b/dispatcher/network/app_socket.go @@ -120,7 +120,7 @@ func (h *AppConnHandler) doRegExchange(appServer *dispatcher.Server) (net.Packet } func (h *AppConnHandler) logRegistration(ia addr.IA, public *net.UDPAddr, bind net.IP, - svc addr.HostSVC) { + svc addr.SVC) { items := []interface{}{"ia", ia, "public", public} if bind != nil { diff --git a/dispatcher/table.go b/dispatcher/table.go index e53060220..e48b40af7 100644 --- a/dispatcher/table.go +++ b/dispatcher/table.go @@ -53,7 +53,7 @@ func (t *IATable) LookupPublic(ia addr.IA, public *net.UDPAddr) (*TableEntry, bo return e.(*TableEntry), true } -func (t *IATable) LookupService(ia addr.IA, svc addr.HostSVC, bind net.IP) []*TableEntry { +func (t *IATable) LookupService(ia addr.IA, svc addr.SVC, bind net.IP) []*TableEntry { ifaces := t.IATable.LookupService(ia, svc, bind) entries := make([]*TableEntry, len(ifaces)) for i := range ifaces { diff --git a/dispatcher/underlay.go b/dispatcher/underlay.go index d42b14dc1..4a09cc22b 100644 --- a/dispatcher/underlay.go +++ b/dispatcher/underlay.go @@ -90,19 +90,19 @@ func getDstUDP(pkt *respool.Packet) (Destination, error) { if err != nil { return nil, err } - switch d := dst.(type) { - case *net.IPAddr: + switch dst.Type() { + case addr.HostTypeIP: return UDPDestination{ IA: pkt.SCION.DstIA, Public: &net.UDPAddr{ - IP: d.IP, + IP: dst.IP().AsSlice(), Port: int(pkt.UDP.DstPort), }, }, nil - case addr.HostSVC: + case addr.HostTypeSVC: return SVCDestination{ IA: pkt.SCION.DstIA, - Svc: d, + Svc: dst.SVC(), }, nil default: return nil, serrors.WithCtx(ErrUnsupportedDestination, "type", common.TypeOf(dst)) @@ -167,14 +167,13 @@ func getDstSCMPErr(pkt *respool.Packet) (Destination, error) { if err != nil { return nil, err } - ipAddr, ok := dst.(*net.IPAddr) - if !ok { - return nil, serrors.WithCtx(ErrUnsupportedDestination, "type", common.TypeOf(dst)) + if dst.Type() != addr.HostTypeIP { + return nil, serrors.WithCtx(ErrUnsupportedDestination, "type", dst.Type()) } return UDPDestination{ IA: pkt.SCION.DstIA, Public: &net.UDPAddr{ - IP: ipAddr.IP, + IP: dst.IP().AsSlice(), Port: port, }, }, nil @@ -234,7 +233,7 @@ func (d UDPDestination) Send(dp *NetToRingDataplane, pkt *respool.Packet) { // service. type SVCDestination struct { IA addr.IA - Svc addr.HostSVC + Svc addr.SVC } func (d SVCDestination) Send(dp *NetToRingDataplane, pkt *respool.Packet) { diff --git a/dispatcher/underlay_test.go b/dispatcher/underlay_test.go index bc08c2109..e7e72a1ed 100644 --- a/dispatcher/underlay_test.go +++ b/dispatcher/underlay_test.go @@ -61,7 +61,7 @@ func TestGetDst(t *testing.T) { }, L4: slayers.LayerTypeSCIONUDP, } - require.NoError(t, pkt.SCION.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 1}})) + require.NoError(t, pkt.SCION.SetDstAddr(addr.MustParseHost("192.168.0.1"))) return pkt }, ExpectedDst: UDPDestination{ @@ -81,7 +81,7 @@ func TestGetDst(t *testing.T) { }, L4: slayers.LayerTypeSCIONUDP, } - require.NoError(t, pkt.SCION.SetDstAddr(addr.SvcCS)) + require.NoError(t, pkt.SCION.SetDstAddr(addr.HostSVC(addr.SvcCS))) return pkt }, ExpectedDst: SVCDestination{ @@ -252,7 +252,7 @@ func TestGetDst(t *testing.T) { }, L4: slayers.LayerTypeSCMP, } - require.NoError(t, pkt.SCION.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 1}})) + require.NoError(t, pkt.SCION.SetDstAddr(addr.MustParseHost("192.168.0.1"))) return pkt }, ExpectedDst: UDPDestination{ @@ -308,7 +308,7 @@ func TestGetDst(t *testing.T) { }, L4: slayers.LayerTypeSCMP, } - require.NoError(t, pkt.SCION.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 1}})) + require.NoError(t, pkt.SCION.SetDstAddr(addr.MustParseHost("192.168.0.1"))) return pkt }, ExpectedDst: SCMPDestination{ @@ -364,7 +364,7 @@ func TestGetDst(t *testing.T) { }, L4: slayers.LayerTypeSCMP, } - require.NoError(t, pkt.SCION.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 1}})) + require.NoError(t, pkt.SCION.SetDstAddr(addr.MustParseHost("192.168.0.1"))) return pkt }, ExpectedDst: SCMPDestination{ @@ -419,7 +419,7 @@ func TestGetDst(t *testing.T) { }, L4: slayers.LayerTypeSCMP, } - require.NoError(t, pkt.SCION.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 1}})) + require.NoError(t, pkt.SCION.SetDstAddr(addr.MustParseHost("192.168.0.1"))) return pkt }, ExpectedDst: UDPDestination{ @@ -476,7 +476,7 @@ func TestGetDst(t *testing.T) { }, L4: slayers.LayerTypeSCMP, } - require.NoError(t, pkt.SCION.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 1}})) + require.NoError(t, pkt.SCION.SetDstAddr(addr.MustParseHost("192.168.0.1"))) return pkt }, ExpectedDst: SCMPDestination{ @@ -533,7 +533,7 @@ func TestGetDst(t *testing.T) { }, L4: slayers.LayerTypeSCMP, } - require.NoError(t, pkt.SCION.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 1}})) + require.NoError(t, pkt.SCION.SetDstAddr(addr.MustParseHost("192.168.0.1"))) return pkt }, ExpectedDst: SCMPDestination{ @@ -588,7 +588,7 @@ func TestGetDst(t *testing.T) { }, L4: slayers.LayerTypeSCMP, } - require.NoError(t, pkt.SCION.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 1}})) + require.NoError(t, pkt.SCION.SetDstAddr(addr.MustParseHost("192.168.0.1"))) return pkt }, ErrAssertion: assert.Error, @@ -641,7 +641,7 @@ func TestGetDst(t *testing.T) { }, L4: slayers.LayerTypeSCMP, } - require.NoError(t, pkt.SCION.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 1}})) + require.NoError(t, pkt.SCION.SetDstAddr(addr.MustParseHost("192.168.0.1"))) return pkt }, ErrAssertion: assert.Error, @@ -859,8 +859,8 @@ func TestSCMPHandlerReverse(t *testing.T) { SCMP: tc.L4(t), L4: slayers.LayerTypeSCMP, } - require.NoError(t, pkt.SCION.SetSrcAddr(&net.IPAddr{IP: net.IP{127, 0, 0, 1}})) - require.NoError(t, pkt.SCION.SetDstAddr(&net.IPAddr{IP: net.IP{127, 0, 0, 2}})) + require.NoError(t, pkt.SCION.SetSrcAddr(addr.MustParseHost("127.0.0.1"))) + require.NoError(t, pkt.SCION.SetDstAddr(addr.MustParseHost("127.0.0.2"))) // Reverse packet raw, err := SCMPHandler{}.reverse(pkt) @@ -902,8 +902,8 @@ func TestSCMPHandlerReverse(t *testing.T) { }, }, } - require.NoError(t, expected.SetSrcAddr(&net.IPAddr{IP: net.IP{127, 0, 0, 2}})) - require.NoError(t, expected.SetDstAddr(&net.IPAddr{IP: net.IP{127, 0, 0, 1}})) + require.NoError(t, expected.SetSrcAddr(addr.MustParseHost("127.0.0.2"))) + require.NoError(t, expected.SetDstAddr(addr.MustParseHost("127.0.0.1"))) scionL.BaseLayer = slayers.BaseLayer{} var decodedPath scion.Decoded @@ -951,7 +951,7 @@ func newSCIONHdr(t *testing.T, l4 slayers.L4ProtocolType) *slayers.SCION { }, }, } - require.NoError(t, scion.SetSrcAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 1}})) - require.NoError(t, scion.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 2}})) + require.NoError(t, scion.SetSrcAddr(addr.MustParseHost("192.168.0.1"))) + require.NoError(t, scion.SetDstAddr(addr.MustParseHost("192.168.0.2"))) return scion } diff --git a/gateway/cmd/gateway/main.go b/gateway/cmd/gateway/main.go index cf509fc36..8796b1863 100644 --- a/gateway/cmd/gateway/main.go +++ b/gateway/cmd/gateway/main.go @@ -20,6 +20,7 @@ import ( "net" "net/http" _ "net/http/pprof" + "net/netip" "github.com/go-chi/chi/v5" "github.com/go-chi/cors" @@ -74,6 +75,10 @@ func realMain(ctx context.Context) error { return serrors.WrapStr("determine default local IP", err) } } + controlAddressIP, ok := netip.AddrFromSlice(controlAddress.IP) + if !ok { + return serrors.New("invalid IP address", "control", controlAddress.IP) + } dataAddress, err := net.ResolveUDPAddr("udp", globalCfg.Gateway.DataAddr) if err != nil { return serrors.WrapStr("parsing data address", err) @@ -135,7 +140,7 @@ func realMain(ctx context.Context) error { ControlServerAddr: controlAddress, ControlClientIP: controlAddress.IP, ServiceDiscoveryClientIP: controlAddress.IP, - PathMonitorIP: controlAddress.IP, + PathMonitorIP: controlAddressIP, ProbeServerAddr: probeAddress, ProbeClientIP: controlAddress.IP, DataServerAddr: dataAddress, diff --git a/gateway/gateway.go b/gateway/gateway.go index 14103af34..d6fe36e58 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -111,14 +111,14 @@ func (pcf PacketConnFactory) New() (net.PacketConn, error) { type ProbeConnFactory struct { Dispatcher *reconnect.DispatcherService LocalIA addr.IA - LocalIP net.IP + LocalIP netip.Addr } func (f ProbeConnFactory) New(ctx context.Context) (net.PacketConn, error) { pathMonitorConnection, pathMonitorPort, err := f.Dispatcher.Register( context.Background(), f.LocalIA, - &net.UDPAddr{IP: f.LocalIP}, + &net.UDPAddr{IP: f.LocalIP.AsSlice()}, addr.SvcNone, ) if err != nil { @@ -186,7 +186,7 @@ type Gateway struct { ServiceDiscoveryClientIP net.IP // PathMonitorIP is the IP that should be used for path monitoring SCMP traceroute traffic. - PathMonitorIP net.IP + PathMonitorIP netip.Addr // ProbeServerAddr is the address for the probe server. The probe server replies // to probe traffic from other gateways. ProbeServerAddr *net.UDPAddr diff --git a/gateway/pathhealth/pathwatcher.go b/gateway/pathhealth/pathwatcher.go index 1116b4df3..99f13d175 100644 --- a/gateway/pathhealth/pathwatcher.go +++ b/gateway/pathhealth/pathwatcher.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "net" + "net/netip" "sync" "time" @@ -49,7 +50,7 @@ type DefaultPathWatcherFactory struct { // LocalIA is the ID of the local AS. LocalIA addr.IA // LocalIP is the IP address of the local host. - LocalIP net.IP + LocalIP netip.Addr // RevocationHandler is the revocation handler. RevocationHandler snet.RevocationHandler // ConnFactory is used to create probe connections. @@ -109,7 +110,7 @@ func (f *DefaultPathWatcherFactory) New( id: id, localAddr: snet.SCIONAddress{ IA: f.LocalIA, - Host: addr.HostFromIP(f.LocalIP), + Host: addr.HostIP(f.LocalIP), }, pktChan: pktChan, probesSent: createCounter(f.ProbesSent, remote), @@ -290,7 +291,7 @@ func (w *pathWatcher) prepareProbePacket() error { Destination: snet.SCIONAddress{ IA: w.remote, // The host doesn't really matter because it's terminated at the router. - Host: addr.SvcNone, + Host: addr.HostSVC(addr.SvcNone), }, Source: w.localAddr, Path: w.path.dpPath, diff --git a/pkg/addr/BUILD.bazel b/pkg/addr/BUILD.bazel index 6c003ea6f..9ee5fd06f 100644 --- a/pkg/addr/BUILD.bazel +++ b/pkg/addr/BUILD.bazel @@ -3,10 +3,12 @@ load("//tools/lint:go.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "addr.go", "doc.go", "fmt.go", "host.go", "isdas.go", + "svc.go", ], importpath = "github.com/scionproto/scion/pkg/addr", visibility = ["//visibility:public"], @@ -16,9 +18,14 @@ go_library( go_test( name = "go_default_test", srcs = [ + "addr_test.go", "host_test.go", "isdas_test.go", + "svc_test.go", ], embed = [":go_default_library"], - deps = ["@com_github_stretchr_testify//assert:go_default_library"], + deps = [ + "@com_github_stretchr_testify//assert:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", + ], ) diff --git a/pkg/addr/addr.go b/pkg/addr/addr.go new file mode 100644 index 000000000..4467f54a4 --- /dev/null +++ b/pkg/addr/addr.go @@ -0,0 +1,117 @@ +// Copyright 2023 SCION Association +// +// 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 addr + +import ( + "fmt" + "net" + "strconv" + "strings" + + "github.com/scionproto/scion/pkg/private/serrors" +) + +// Addr is a full SCION address, composed of ISD, AS and Host part. +type Addr struct { + IA IA + Host Host +} + +// ParseAddr parses s as an address in the format -,, +// returning the result as an Addr. +func ParseAddr(s string) (Addr, error) { + comma := strings.IndexByte(s, ',') + if comma < 0 { + return Addr{}, serrors.New("invalid address: expected comma", "value", s) + } + ia, err := ParseIA(s[0:comma]) + if err != nil { + return Addr{}, err + } + h, err := ParseHost(s[comma+1:]) + if err != nil { + return Addr{}, err + } + return Addr{IA: ia, Host: h}, nil +} + +// MustParseAddr calls ParseAddr(s) and panics on error. +// It is intended for use in tests with hard-coded strings. +func MustParseAddr(s string) Addr { + a, err := ParseAddr(s) + if err != nil { + panic(err) + } + return a +} + +func (a Addr) String() string { + return fmt.Sprintf("%s,%s", a.IA, a.Host) +} + +// Set implements flag.Value interface +func (a *Addr) Set(s string) error { + pA, err := ParseAddr(s) + if err != nil { + return err + } + *a = pA + return nil +} + +func (a Addr) MarshalText() ([]byte, error) { + return []byte(a.String()), nil +} + +func (a *Addr) UnmarshalText(b []byte) error { + return a.Set(string(b)) +} + +// ParseAddrPort parses s as a SCION address with a port, in the format +// +// [-,]:. +// +// Examples: +// - [isd-as,svc]:port (e.g., [1-ff00:0:110,CS]:80) +// - [isd-as,ipv4]:port (e.g., [1-ff00:0:110,192.0.2.1]:80) +// - [isd-as,ipv6%zone]:port (e.g., [1-ff00:0:110,2001:DB8::1%zone]:80) +// +// EXPERIMENTAL: This API is experimental. It may be changed to return a +// combined AddrPort type instead. +func ParseAddrPort(s string) (Addr, uint16, error) { + host, port, err := net.SplitHostPort(s) + if err != nil { + return Addr{}, 0, serrors.WrapStr("invalid address: split host:port", err, "addr", s) + } + a, err := ParseAddr(host) + if err != nil { + return Addr{}, 0, serrors.WrapStr("invalid address: host invalid", err, "host", host) + } + p, err := strconv.ParseUint(port, 10, 16) + if err != nil { + return Addr{}, 0, serrors.WrapStr("invalid address: port invalid", err, "port", port) + } + return a, uint16(p), nil +} + +// FormatAddrPort formats an Addr with a port to the format +// +// [-,]:. +// +// EXPERIMENTAL: This API is experimental. It may be changed to a String() +// function an a combined AddrPort type instead. +func FormatAddrPort(a Addr, port uint16) string { + return fmt.Sprintf("[%s]:%d", a, port) +} diff --git a/pkg/addr/addr_test.go b/pkg/addr/addr_test.go new file mode 100644 index 000000000..b3056c3e8 --- /dev/null +++ b/pkg/addr/addr_test.go @@ -0,0 +1,221 @@ +// Copyright 2023 SCION Association +// +// 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 addr_test + +import ( + "encoding" + "flag" + "fmt" + "net/netip" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/pkg/addr" +) + +func ExampleParseAddr() { + a, err := addr.ParseAddr("6-ffaa:0:123,198.51.100.1") + fmt.Printf("ia: %v, host type: %v, host: %v, err: %v\n", a.IA, a.Host.Type(), a.Host, err) + // Output: ia: 6-ffaa:0:123, host type: IP, host: 198.51.100.1, err: +} + +func ExampleParseAddr_svc() { + a, err := addr.ParseAddr("6-ffaa:0:123,CS") + fmt.Printf("ia: %v, host type: %v, host: %v, err: %v\n", a.IA, a.Host.Type(), a.Host, err) + // Output: ia: 6-ffaa:0:123, host type: SVC, host: CS, err: +} + +func TestParseAddr(t *testing.T) { + invalid := []string{ + "", + ",", + "a", + "0-0::", + "0-0,::,", + "1,ffaa:0:1101::", + "65536-1,ff00::1", + "[1-ffaa:0:1101,127.0.0.1]", + } + for _, s := range invalid { + t.Run(s, func(t *testing.T) { + _, err := addr.ParseAddr(s) + assert.Error(t, err) + }) + t.Run("unmarshal "+s, func(t *testing.T) { + var a addr.Addr + var u encoding.TextUnmarshaler = &a + err := u.UnmarshalText([]byte(s)) + assert.Error(t, err) + assert.Equal(t, addr.Addr{}, a) + }) + t.Run("set "+s, func(t *testing.T) { + var a addr.Addr + var v flag.Value = &a + err := v.Set(s) + assert.Error(t, err) + assert.Equal(t, addr.Addr{}, a) + }) + } + + valid := map[string]addr.Addr{ + "0-0,::": { + IA: addr.MustIAFrom(0, 0), + Host: addr.HostIP(netip.AddrFrom16([16]byte{})), + }, + "0-0,0.0.0.0": { + IA: addr.MustIAFrom(0, 0), + Host: addr.HostIP(netip.AddrFrom4([4]byte{})), + }, + "1-ffaa:0:1101,::1": { + IA: addr.MustIAFrom(1, 0xffaa_0000_1101), + Host: addr.HostIP(netip.AddrFrom16( + [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + )), + }, + "1-ffaa:0:1101,127.0.0.1": { + IA: addr.MustIAFrom(1, 0xffaa_0000_1101), + Host: addr.HostIP(netip.AddrFrom4([4]byte{127, 0, 0, 1})), + }, + "1-ffaa:0:1101,CS": { + IA: addr.MustIAFrom(1, 0xffaa_0000_1101), + Host: addr.HostSVC(addr.SvcCS), + }, + "65535-1,ff00::1": { + IA: addr.MustIAFrom(65535, 1), + Host: addr.HostIP(netip.AddrFrom16( + [16]byte{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + )), + }, + "1-1:fcd1:1,::ffff:192.0.2.128": { + IA: addr.MustIAFrom(1, 0x0001_fcd1_0001), + Host: addr.HostIP(netip.AddrFrom16( + [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 0, 2, 128}, + )), + }, + } + for s, expected := range valid { + t.Run(s, func(t *testing.T) { + a, err := addr.ParseAddr(s) + require.NoError(t, err) + assert.Equal(t, expected, a) + }) + t.Run("unmarshal "+s, func(t *testing.T) { + var a addr.Addr + var u encoding.TextUnmarshaler = &a + err := u.UnmarshalText([]byte(s)) + require.NoError(t, err) + assert.Equal(t, expected, a) + }) + t.Run("set "+s, func(t *testing.T) { + var a addr.Addr + var v flag.Value = &a + err := v.Set(s) + require.NoError(t, err) + assert.Equal(t, expected, a) + }) + } +} + +func TestParseAddrPort(t *testing.T) { + invalid := []string{ + "", + "[]", + "[]:", + "[0-0,::]:65536", + "[0-0,::]:http", + "[0-0,::]:a", + "[1-ffaa:0:1101,127.0.0.1]", + "[1-ffaa:0:1101,127.0.0.1]:0xff", + "[1-ffaa:0:1101,127.0.0.1]:ff", + "[1-ffaa:0:1101,127.0.0.1]:-1", + "[1-ffaa:0:1101,127.0.0.1]:666666", + } + for _, s := range invalid { + t.Run(s, func(t *testing.T) { + _, _, err := addr.ParseAddrPort(s) + assert.Error(t, err) + }) + } + + valid := map[string]struct { + IA addr.IA + Host addr.Host + Port uint16 + }{ + "[0-0,::]:0": { + IA: addr.MustIAFrom(0, 0), + Host: addr.HostIP(netip.AddrFrom16([16]byte{})), + Port: 0, + }, + "[0-0,::]:65535": { + IA: addr.MustIAFrom(0, 0), + Host: addr.HostIP(netip.AddrFrom16([16]byte{})), + Port: 65535, + }, + "[0-0,0.0.0.0]:1234": { + IA: addr.MustIAFrom(0, 0), + Host: addr.HostIP(netip.AddrFrom4([4]byte{})), + Port: 1234, + }, + "[1-ffaa:0:1101,::1]:54321": { + IA: addr.MustIAFrom(1, 0xffaa_0000_1101), + Host: addr.HostIP(netip.AddrFrom16( + [16]byte{15: 1}, + )), + Port: 54321, + }, + "[1-ffaa:0:1101,127.0.0.1]:010": { + IA: addr.MustIAFrom(1, 0xffaa_0000_1101), + Host: addr.HostIP(netip.AddrFrom4([4]byte{127, 0, 0, 1})), + Port: 10, + }, + "[1-ffaa:0:1101,CS]:42": { + IA: addr.MustIAFrom(1, 0xffaa_0000_1101), + Host: addr.HostSVC(addr.SvcCS), + Port: 42, + }, + "[65535-1,ff00::1]:8888": { + IA: addr.MustIAFrom(65535, 1), + Host: addr.HostIP(netip.AddrFrom16( + [16]byte{0: 0xff, 15: 1}, + )), + Port: 8888, + }, + "[1-1:fcd1:1,::ffff:192.0.2.128]:0000000000000000000080": { + IA: addr.MustIAFrom(1, 0x0001_fcd1_0001), + Host: addr.HostIP(netip.AddrFrom16( + [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 0, 2, 128}, + )), + Port: 80, + }, + } + + for s, expected := range valid { + t.Run(s, func(t *testing.T) { + a, port, err := addr.ParseAddrPort(s) + require.NoError(t, err) + assert.Equal(t, addr.Addr{IA: expected.IA, Host: expected.Host}, a) + assert.Equal(t, expected.Port, port) + + fmted := addr.FormatAddrPort(a, port) + if !strings.Contains(s, "]:0") { // skip cases where port has leading 0s + assert.Equal(t, s, fmted) + } + }) + } +} diff --git a/pkg/addr/doc.go b/pkg/addr/doc.go index 26382813a..ae493bfa0 100644 --- a/pkg/addr/doc.go +++ b/pkg/addr/doc.go @@ -18,6 +18,9 @@ Package addr contains types for SCION addressing. A SCION address is composed of the following parts: ISD (ISolation Domain identifier), AS (Autonomous System idenifier), and Host (the host address). +The ISD-AS parts are often considered together. Conventionally, this is +abbreviated to "IA". + The allocations and formatting of ISDs and ASes are documented here: https://github.com/scionproto/scion/wiki/ISD-and-AS-numbering. Note that the ':' separator for AS formatting is not used in paths/filenames for diff --git a/pkg/addr/host.go b/pkg/addr/host.go index 69ffba2f5..d6f157e54 100644 --- a/pkg/addr/host.go +++ b/pkg/addr/host.go @@ -1,5 +1,6 @@ // Copyright 2016 ETH Zurich // Copyright 2018 ETH Zurich, Anapaya Systems +// Copyright 2022 ETH Zurich, Anapaya Systems, SCION Association // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,20 +17,16 @@ package addr import ( - "encoding/binary" "fmt" - "net" - "strings" - - "github.com/scionproto/scion/pkg/private/serrors" + "net/netip" ) +// HostAddrType discriminates between different types of Host addresses. type HostAddrType uint8 const ( HostTypeNone HostAddrType = iota - HostTypeIPv4 - HostTypeIPv6 + HostTypeIP HostTypeSVC ) @@ -37,313 +34,103 @@ func (t HostAddrType) String() string { switch t { case HostTypeNone: return "None" - case HostTypeIPv4: - return "IPv4" - case HostTypeIPv6: - return "IPv6" + case HostTypeIP: + return "IP" case HostTypeSVC: return "SVC" } return fmt.Sprintf("UNKNOWN (%d)", t) } -const ( - HostLenNone = 0 - HostLenIPv4 = net.IPv4len - HostLenIPv6 = net.IPv6len - HostLenSVC = 2 -) - -var ( - // ErrBadHostAddrType indicates an invalid host address type. - ErrBadHostAddrType = serrors.New("unsupported host address type") - // ErrMalformedHostAddrType indicates a malformed host address type. - ErrMalformedHostAddrType = serrors.New("malformed host address type") - // ErrUnsupportedSVCAddress indicates an unsupported SVC address. - ErrUnsupportedSVCAddress = serrors.New("unsupported SVC address") -) - -const ( - SvcDS HostSVC = 0x0001 - SvcCS HostSVC = 0x0002 - SvcWildcard HostSVC = 0x0010 - SvcNone HostSVC = 0xffff - - SVCMcast HostSVC = 0x8000 -) - -type HostAddr interface { - Size() int - Type() HostAddrType - Pack() []byte - IP() net.IP - Copy() HostAddr - Equal(HostAddr) bool - fmt.Stringer -} - -var _ HostAddr = (HostNone)(nil) - -type HostNone net.IP - -func (h HostNone) Size() int { - return HostLenNone -} - -func (h HostNone) Type() HostAddrType { - return HostTypeNone -} - -func (h HostNone) Pack() []byte { - return []byte{} -} - -func (h HostNone) IP() net.IP { - return nil -} - -func (h HostNone) Copy() HostAddr { - return HostNone{} -} - -func (h HostNone) Equal(o HostAddr) bool { - _, ok := o.(HostNone) - return ok -} - -func (h HostNone) String() string { - return "" -} - -var _ HostAddr = (HostIPv4)(nil) - -type HostIPv4 net.IP - -func (h HostIPv4) Size() int { - return HostLenIPv4 -} - -func (h HostIPv4) Type() HostAddrType { - return HostTypeIPv4 -} - -func (h HostIPv4) Pack() []byte { - return []byte(h.IP()) -} - -func (h HostIPv4) IP() net.IP { - // XXX(kormat): ensure the reply is the 4-byte representation. - return net.IP(h).To4() -} - -func (h HostIPv4) Copy() HostAddr { - return HostIPv4(append(net.IP(nil), h...)) -} - -func (h HostIPv4) Equal(o HostAddr) bool { - ha, ok := o.(HostIPv4) - return ok && net.IP(h).Equal(net.IP(ha)) -} - -func (h HostIPv4) String() string { - return h.IP().String() -} - -var _ HostAddr = (HostIPv6)(nil) - -type HostIPv6 net.IP - -func (h HostIPv6) Size() int { - return HostLenIPv6 -} - -func (h HostIPv6) Type() HostAddrType { - return HostTypeIPv6 -} - -func (h HostIPv6) Pack() []byte { - return []byte(h)[:HostLenIPv6] -} - -func (h HostIPv6) IP() net.IP { - return net.IP(h) -} - -func (h HostIPv6) Copy() HostAddr { - return HostIPv6(append(net.IP(nil), h...)) -} - -func (h HostIPv6) Equal(o HostAddr) bool { - ha, ok := o.(HostIPv6) - return ok && net.IP(h).Equal(net.IP(ha)) -} - -func (h HostIPv6) String() string { - return h.IP().String() -} - -var _ HostAddr = (*HostSVC)(nil) - -type HostSVC uint16 - -// HostSVCFromString returns the SVC address corresponding to str. For anycast -// SVC addresses, use BS_A, PS_A, CS_A, and SB_A; shorthand versions without -// the _A suffix (e.g., PS) also return anycast SVC addresses. For multicast, -// use BS_M, PS_M, CS_M, and SB_M. -func HostSVCFromString(str string) HostSVC { - var m HostSVC - switch { - case strings.HasSuffix(str, "_A"): - str = strings.TrimSuffix(str, "_A") - case strings.HasSuffix(str, "_M"): - str = strings.TrimSuffix(str, "_M") - m = SVCMcast +// Host represents the AS-local host identifier of a SCION address. +// +// Different address types (IPv4, IPv6, SVC) are all represented with +// this Host struct, discriminated with a Type() field. +// +// The zero value is a valid object with Host{}.Type() == HostTypeNone. +type Host struct { + ip netip.Addr + svc SVC + t HostAddrType +} + +// ParseHost parses s as either a service address or an IP address, +// returning the result as a Host address. +// s can either be a SVC address, in the format supported by ParseSVC(s), +// or an IP address in dotted decimal or IPv6 format. +func ParseHost(s string) (Host, error) { + svc, err := ParseSVC(s) + if err == nil { + return HostSVC(svc), nil } - switch str { - case "DS": - return SvcDS | m - case "CS": - return SvcCS | m - case "Wildcard": - return SvcWildcard | m - default: - return SvcNone + ip, err := netip.ParseAddr(s) + if err != nil { + return Host{}, err } + return HostIP(ip), nil } -func (h HostSVC) Size() int { - return HostLenSVC -} - -func (h HostSVC) Type() HostAddrType { - return HostTypeSVC -} - -func (h HostSVC) Pack() []byte { - out := make([]byte, HostLenSVC) - binary.BigEndian.PutUint16(out, uint16(h)) - return out -} - -func (h HostSVC) PackWithPad(pad int) []byte { - out := make([]byte, HostLenSVC+pad) - binary.BigEndian.PutUint16(out, uint16(h)) - return out -} - -func (h HostSVC) IP() net.IP { - return nil -} - -func (h HostSVC) IsMulticast() bool { - return (h & SVCMcast) != 0 -} - -func (h HostSVC) Base() HostSVC { - return h & ^SVCMcast -} - -func (h HostSVC) Multicast() HostSVC { - return h | SVCMcast -} - -func (h HostSVC) Copy() HostAddr { - return h -} - -func (h HostSVC) Equal(o HostAddr) bool { - ha, ok := o.(HostSVC) - return ok && h == ha -} - -func (h HostSVC) String() string { - name := h.BaseString() - cast := 'A' - if h.IsMulticast() { - cast = 'M' +// MustParseHost calls ParseHost(s) and panics on error. +// It is intended for use in tests with hard-coded strings. +func MustParseHost(s string) Host { + host, err := ParseHost(s) + if err != nil { + panic(err) } - return fmt.Sprintf("%v %c (0x%04x)", name, cast, uint16(h)) + return host } -// BaseString returns the upper case name of the service. For hosts or unrecognized services, it -// returns UNKNOWN. -func (h HostSVC) BaseString() string { - switch h.Base() { - case SvcDS: - return "DS" - case SvcCS: - return "CS" - case SvcWildcard: - return "Wildcard" - default: - return "UNKNOWN" - } +// HostIP returns a Host address representing ip, with type HostTypeIP. +func HostIP(ip netip.Addr) Host { + return Host{t: HostTypeIP, ip: ip} } -func (h HostSVC) Network() string { - return "" +// HostSvc returns a Host address representing svc, with type HostTypeSVC. +func HostSVC(svc SVC) Host { + return Host{t: HostTypeSVC, svc: svc} } -func HostFromRaw(b []byte, htype HostAddrType) (HostAddr, error) { - switch htype { - case HostTypeNone: - return HostNone{}, nil - case HostTypeIPv4: - if len(b) < HostLenIPv4 { - return nil, serrors.WithCtx(ErrMalformedHostAddrType, "type", htype) - } - return HostIPv4(b[:HostLenIPv4]), nil - case HostTypeIPv6: - if len(b) < HostLenIPv6 { - return nil, serrors.WithCtx(ErrMalformedHostAddrType, "type", htype) - } - return HostIPv6(b[:HostLenIPv6]), nil - case HostTypeSVC: - if len(b) < HostLenSVC { - return nil, serrors.WithCtx(ErrMalformedHostAddrType, "type", htype) - } - return HostSVC(binary.BigEndian.Uint16(b)), nil - default: - return nil, serrors.WithCtx(ErrBadHostAddrType, "type", htype) - } +// Type returns the type of the address represented by h. +func (h Host) Type() HostAddrType { + return h.t } -func HostFromIP(ip net.IP) HostAddr { - if ip4 := ip.To4(); ip4 != nil { - return HostIPv4(ip4) +// IP returns the IP address represented by h. +// Panics if h.Type() is not HostTypeIP. +func (h Host) IP() netip.Addr { + if h.t != HostTypeIP { + panic("IP called on non-IP address") } - return HostIPv6(ip) + return h.ip } -func HostFromIPStr(s string) HostAddr { - ip := net.ParseIP(s) - if ip == nil { - return nil +// SVC returns the SVC address represented by h. +// Panics if h.Type() is not HostTypeSVC. +func (h Host) SVC() SVC { + if h.t != HostTypeSVC { + panic("SVC called on non-SVC address") } - return HostFromIP(ip) + return h.svc } -func HostLen(htype HostAddrType) (uint8, error) { - var length uint8 - switch htype { +func (h Host) String() string { + switch h.Type() { case HostTypeNone: - length = HostLenNone - case HostTypeIPv4: - length = HostLenIPv4 - case HostTypeIPv6: - length = HostLenIPv6 + return "" + case HostTypeIP: + return h.ip.String() case HostTypeSVC: - length = HostLenSVC - default: - return 0, serrors.WithCtx(ErrBadHostAddrType, "type", htype) + return h.svc.String() } - return length, nil + panic("unsupported host type") } -func HostTypeCheck(t HostAddrType) bool { - switch t { - case HostTypeIPv6, HostTypeIPv4, HostTypeSVC: - return true +// Set implements flag.Value interface +func (h *Host) Set(s string) error { + pH, err := ParseHost(s) + if err != nil { + return err } - return false + *h = pH + return nil } diff --git a/pkg/addr/host_test.go b/pkg/addr/host_test.go index 7f0272ede..d8da6eada 100644 --- a/pkg/addr/host_test.go +++ b/pkg/addr/host_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 ETH Zurich, Anapaya Systems +// Copyright 2023 SCION Association // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,72 +15,146 @@ package addr_test import ( - "net" + "fmt" + "net/netip" + "reflect" + "runtime" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/scionproto/scion/pkg/addr" ) -func TestHostFromRaw(t *testing.T) { - testCases := map[string]struct { - input []byte - addrType addr.HostAddrType - expected addr.HostAddr - errAssertion assert.ErrorAssertionFunc - }{ - "nil IPv4": { - addrType: addr.HostTypeIPv4, - errAssertion: assert.Error, - }, - "short IPv4": { - input: make([]byte, 3), - addrType: addr.HostTypeIPv4, - errAssertion: assert.Error, - }, - "valid IPv4": { - input: []byte{127, 0, 0, 1}, - addrType: addr.HostTypeIPv4, - expected: addr.HostFromIP(net.IPv4(127, 0, 0, 1)), - errAssertion: assert.NoError, - }, - "nil IPv6": { - addrType: addr.HostTypeIPv6, - errAssertion: assert.Error, - }, - "short IPv6": { - input: make([]byte, 14), - addrType: addr.HostTypeIPv6, - errAssertion: assert.Error, - }, - "valid IPv6": { - input: net.ParseIP("dead::beef"), - addrType: addr.HostTypeIPv6, - expected: addr.HostFromIP(net.ParseIP("dead::beef")), - errAssertion: assert.NoError, - }, - "nil SVC": { - addrType: addr.HostTypeSVC, - errAssertion: assert.Error, - }, - "short SVC": { - input: make([]byte, 1), - addrType: addr.HostTypeSVC, - errAssertion: assert.Error, - }, - "valid SVC": { - input: addr.SvcDS.Pack(), - addrType: addr.HostTypeSVC, - expected: addr.SvcDS, - errAssertion: assert.NoError, - }, +func ExampleHost() { + hs := []addr.Host{ + {}, + addr.HostIP(netip.MustParseAddr("::1")), + addr.HostIP(netip.AddrFrom4([4]byte{198, 51, 100, 1})), + addr.HostSVC(addr.SvcCS), } - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - got, err := addr.HostFromRaw(tc.input, tc.addrType) - tc.errAssertion(t, err) - assert.Equal(t, tc.expected, got) + for _, h := range hs { + fmt.Printf("h: %q, h.Type(): %q", h, h.Type()) + switch h.Type() { + case addr.HostTypeIP: + fmt.Printf(", h.IP().Is4(): %v", h.IP().Is4()) + case addr.HostTypeSVC: + fmt.Printf(", h.SVC().IsMulticast(): %v", h.SVC().IsMulticast()) + default: + fmt.Printf(", h == addr.Host{}: %v", h == addr.Host{}) + } + fmt.Println() + } + + // Use Host as map key: + stuff := make(map[addr.Host]struct{}) + for _, h := range hs { + stuff[h] = struct{}{} + } + _, hasSvcCS := stuff[addr.HostSVC(addr.SvcCS)] + _, hasSvcDS := stuff[addr.HostSVC(addr.SvcDS)] + fmt.Printf("has SvcCS: %v, has SvcDS: %v", hasSvcCS, hasSvcDS) + + // Output: + // h: "", h.Type(): "None", h == addr.Host{}: true + // h: "::1", h.Type(): "IP", h.IP().Is4(): false + // h: "198.51.100.1", h.Type(): "IP", h.IP().Is4(): true + // h: "CS", h.Type(): "SVC", h.SVC().IsMulticast(): false + // has SvcCS: true, has SvcDS: false +} + +func TestHostStructSize(t *testing.T) { + if runtime.GOARCH != `amd64` { + t.SkipNow() + } + ipv6 := 16 + zonePtr := 8 + svc := 2 + typ := 1 + padding := 5 + expected := ipv6 + zonePtr + svc + typ + padding + + sizeofHost := int(reflect.TypeOf(addr.Host{}).Size()) + assert.Equal(t, expected, sizeofHost) +} + +func TestParseHost(t *testing.T) { + invalid := []string{ + "", + "x", + "512.0.0.1", + "10.1234567", + "::ffff1", + "2001:0db8:85a3:0000:0000:8a2e:0370:7334:1", // too long + " ::1", + "::1 ", + "localhost", + "CS_X", // almost a service addr + } + for _, s := range invalid { + t.Run(s, func(t *testing.T) { + _, err := addr.ParseHost(s) + assert.Error(t, err) + }) + } + + ipv6 := []string{ + "::", + "::1", + "::ff02:1", + "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "fe80::1ff:fe23:4567:890a%eth2", + "::ffff:192.0.2.128", + "ff00::", + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + } + for _, s := range ipv6 { + t.Run(s, func(t *testing.T) { + h, err := addr.ParseHost(s) + require.NoError(t, err) + require.Equal(t, addr.HostTypeIP, h.Type()) + assert.True(t, h.IP().Is6()) + assert.Equal(t, netip.MustParseAddr(s), h.IP()) + }) + } + + ipv4 := []string{ + "0.0.0.0", + "127.0.0.1", + "198.51.100.0", + "198.51.100.1", + "198.51.100.254", + "198.51.100.255", + "255.255.255.255", + } + for _, s := range ipv4 { + t.Run(s, func(t *testing.T) { + h, err := addr.ParseHost(s) + require.NoError(t, err) + require.Equal(t, addr.HostTypeIP, h.Type()) + assert.True(t, h.IP().Is4()) + assert.Equal(t, netip.MustParseAddr(s), h.IP()) + }) + } + + svcs := map[string]addr.SVC{ + "CS": addr.SvcCS, + "DS": addr.SvcDS, + "Wildcard": addr.SvcWildcard, + "CS_A": addr.SvcCS, + "DS_A": addr.SvcDS, + "Wildcard_A": addr.SvcWildcard, + "CS_M": addr.SvcCS.Multicast(), + "DS_M": addr.SvcDS.Multicast(), + "Wildcard_M": addr.SvcWildcard.Multicast(), + } + for src, svc := range svcs { + t.Run(src, func(t *testing.T) { + h, err := addr.ParseHost(src) + require.NoError(t, err) + require.Equal(t, addr.HostTypeSVC, h.Type()) + assert.Equal(t, svc, h.SVC()) }) } } diff --git a/pkg/addr/svc.go b/pkg/addr/svc.go new file mode 100644 index 000000000..d69ab926b --- /dev/null +++ b/pkg/addr/svc.go @@ -0,0 +1,106 @@ +// Copyright 2022 SCION Association +// +// 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 addr + +import ( + "fmt" + "strings" + + "github.com/scionproto/scion/pkg/private/serrors" +) + +const ( + SvcDS SVC = 0x0001 + SvcCS SVC = 0x0002 + SvcWildcard SVC = 0x0010 + SvcNone SVC = 0xffff + + SVCMcast SVC = 0x8000 +) + +var ( + // ErrUnsupportedSVCAddress indicates an unsupported SVC address. + ErrUnsupportedSVCAddress = serrors.New("unsupported SVC address") +) + +// SVC is a SCION service address. +// A service address is a short identifier for the service type, and a +// flag-bit for multicast. +// The package's SVC constant values are defined without multicast. +// The Multicast and Base methods set/unset the multicast flag. +type SVC uint16 + +// ParseSVC returns the SVC address corresponding to str. For anycast +// SVC addresses, use CS_A and DS_A; shorthand versions without +// the _A suffix (e.g., CS) also return anycast SVC addresses. For multicast, +// use CS_M, and DS_M. +func ParseSVC(str string) (SVC, error) { + var m SVC + switch { + case strings.HasSuffix(str, "_A"): + str = strings.TrimSuffix(str, "_A") + case strings.HasSuffix(str, "_M"): + str = strings.TrimSuffix(str, "_M") + m = SVCMcast + } + switch str { + case "DS": + return SvcDS | m, nil + case "CS": + return SvcCS | m, nil + case "Wildcard": + return SvcWildcard | m, nil + default: + return SvcNone, serrors.New("invalid service address", "value", str) + } +} + +// IsMulticast returns the value of the multicast flag. +func (h SVC) IsMulticast() bool { + return (h & SVCMcast) != 0 +} + +// Base returns the SVC identifier with the multicast flag unset. +func (h SVC) Base() SVC { + return h & ^SVCMcast +} + +// Multicast returns the SVC identifier with the multicast flag set. +func (h SVC) Multicast() SVC { + return h | SVCMcast +} + +func (h SVC) String() string { + s := h.BaseString() + if h.IsMulticast() { + s += "_M" + } + return s +} + +// BaseString returns the upper case name of the service. For unrecognized services, it +// returns "". +func (h SVC) BaseString() string { + switch h.Base() { + case SvcDS: + return "DS" + case SvcCS: + return "CS" + case SvcWildcard: + return "Wildcard" + default: + return fmt.Sprintf("", uint16(h)) + } +} diff --git a/pkg/addr/svc_test.go b/pkg/addr/svc_test.go new file mode 100644 index 000000000..2af253df2 --- /dev/null +++ b/pkg/addr/svc_test.go @@ -0,0 +1,78 @@ +// Copyright 2023 SCION Association +// +// 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 addr_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/scionproto/scion/pkg/addr" +) + +func TestParseSVC(t *testing.T) { + invalid := []string{ + "", + "garbage", + "CS_Y", + "cs_a", + "cs_m", + "CS ", + " CS", + } + for _, src := range invalid { + t.Run(src, func(t *testing.T) { + _, err := addr.ParseSVC(src) + assert.Error(t, err) + }) + } + + valid := map[string]addr.SVC{ + "CS": addr.SvcCS, + "DS": addr.SvcDS, + "Wildcard": addr.SvcWildcard, + "CS_A": addr.SvcCS, + "DS_A": addr.SvcDS, + "Wildcard_A": addr.SvcWildcard, + "CS_M": addr.SvcCS.Multicast(), + "DS_M": addr.SvcDS.Multicast(), + "Wildcard_M": addr.SvcWildcard.Multicast(), + } + for src, svc := range valid { + t.Run(src, func(t *testing.T) { + v, err := addr.ParseSVC(src) + assert.NoError(t, err) + assert.Equal(t, svc, v) + }) + } +} + +func TestSVCString(t *testing.T) { + cases := map[addr.SVC]string{ + addr.SVC(0xABC): "", + addr.SvcCS: "CS", + addr.SvcCS.Multicast(): "CS_M", + addr.SvcDS: "DS", + addr.SvcDS.Multicast(): "DS_M", + addr.SvcWildcard: "Wildcard", + addr.SvcWildcard.Multicast(): "Wildcard_M", + } + for svc, expected := range cases { + t.Run(expected, func(t *testing.T) { + actual := svc.String() + assert.Equal(t, expected, actual) + }) + } +} diff --git a/pkg/daemon/apitypes.go b/pkg/daemon/apitypes.go index bdbdabe75..4b4564bef 100644 --- a/pkg/daemon/apitypes.go +++ b/pkg/daemon/apitypes.go @@ -65,11 +65,11 @@ type TopoQuerier struct { } // UnderlayAnycast provides any address for the given svc type. -func (h TopoQuerier) UnderlayAnycast(ctx context.Context, svc addr.HostSVC) (*net.UDPAddr, error) { +func (h TopoQuerier) UnderlayAnycast(ctx context.Context, svc addr.SVC) (*net.UDPAddr, error) { if err := checkSVC(svc); err != nil { return nil, err } - r, err := h.Connector.SVCInfo(ctx, []addr.HostSVC{svc}) + r, err := h.Connector.SVCInfo(ctx, []addr.SVC{svc}) if err != nil { return nil, err } @@ -84,7 +84,7 @@ func (h TopoQuerier) UnderlayAnycast(ctx context.Context, svc addr.HostSVC) (*ne return &net.UDPAddr{IP: a.IP, Port: topology.EndhostPort, Zone: a.Zone}, nil } -func checkSVC(svc addr.HostSVC) error { +func checkSVC(svc addr.SVC) error { switch svc { case addr.SvcCS: return nil diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go index 3fd60619c..24d0b6b9f 100644 --- a/pkg/daemon/daemon.go +++ b/pkg/daemon/daemon.go @@ -78,7 +78,7 @@ type Connector interface { // service types. If unset, a fresh (i.e., uncached) answer containing all // service types is returned. The reply is a map from service type to a list // of URIs of the service in the local AS. - SVCInfo(ctx context.Context, svcTypes []addr.HostSVC) (map[addr.HostSVC][]string, error) + SVCInfo(ctx context.Context, svcTypes []addr.SVC) (map[addr.SVC][]string, error) // RevNotification sends a RevocationInfo message to the daemon. RevNotification(ctx context.Context, revInfo *path_mgmt.RevInfo) error // DRKeyGetASHostKey requests a AS-Host Key from the daemon. diff --git a/pkg/daemon/grpc.go b/pkg/daemon/grpc.go index 2903a276c..26ae049d7 100644 --- a/pkg/daemon/grpc.go +++ b/pkg/daemon/grpc.go @@ -131,8 +131,8 @@ func (c grpcConn) IFInfo(ctx context.Context, func (c grpcConn) SVCInfo( ctx context.Context, - _ []addr.HostSVC, -) (map[addr.HostSVC][]string, error) { + _ []addr.SVC, +) (map[addr.SVC][]string, error) { client := sdpb.NewDaemonServiceClient(c.conn) response, err := client.Services(ctx, &sdpb.ServicesRequest{}) @@ -140,7 +140,7 @@ func (c grpcConn) SVCInfo( c.metrics.incServcies(err) return nil, err } - result := make(map[addr.HostSVC][]string) + result := make(map[addr.SVC][]string) for st, si := range response.Services { svc := topoServiceTypeToSVCAddr(topology.ServiceTypeFromString(st)) if svc == addr.SvcNone || len(si.Services) == 0 { @@ -315,7 +315,7 @@ func linkTypeFromPB(lt sdpb.LinkType) snet.LinkType { } } -func topoServiceTypeToSVCAddr(st topology.ServiceType) addr.HostSVC { +func topoServiceTypeToSVCAddr(st topology.ServiceType) addr.SVC { switch st { case topology.Control: return addr.SvcCS diff --git a/pkg/daemon/mock_daemon/mock.go b/pkg/daemon/mock_daemon/mock.go index 0bc1388f4..61c85508c 100644 --- a/pkg/daemon/mock_daemon/mock.go +++ b/pkg/daemon/mock_daemon/mock.go @@ -175,10 +175,10 @@ func (mr *MockConnectorMockRecorder) RevNotification(arg0, arg1 interface{}) *go } // SVCInfo mocks base method. -func (m *MockConnector) SVCInfo(arg0 context.Context, arg1 []addr.HostSVC) (map[addr.HostSVC][]string, error) { +func (m *MockConnector) SVCInfo(arg0 context.Context, arg1 []addr.SVC) (map[addr.SVC][]string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SVCInfo", arg0, arg1) - ret0, _ := ret[0].(map[addr.HostSVC][]string) + ret0, _ := ret[0].(map[addr.SVC][]string) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/pkg/drkey/generic/BUILD.bazel b/pkg/drkey/generic/BUILD.bazel index 1655a57ff..afd06f2b2 100644 --- a/pkg/drkey/generic/BUILD.bazel +++ b/pkg/drkey/generic/BUILD.bazel @@ -6,8 +6,10 @@ go_library( importpath = "github.com/scionproto/scion/pkg/drkey/generic", visibility = ["//visibility:public"], deps = [ + "//pkg/addr:go_default_library", "//pkg/drkey:go_default_library", "//pkg/private/serrors:go_default_library", + "//pkg/slayers:go_default_library", ], ) diff --git a/pkg/drkey/generic/generic.go b/pkg/drkey/generic/generic.go index d6e20cb52..d69018097 100644 --- a/pkg/drkey/generic/generic.go +++ b/pkg/drkey/generic/generic.go @@ -17,8 +17,10 @@ package generic import ( "encoding/binary" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/slayers" ) // Deriver implements the level 2/3 generic drkey derivation. @@ -32,13 +34,16 @@ func (d Deriver) DeriveASHost( key drkey.Key, ) (drkey.Key, error) { - host, err := drkey.HostAddrFromString(dstHost) + host, err := addr.ParseHost(dstHost) if err != nil { return drkey.Key{}, serrors.WrapStr("parsing dst host", err) } buf := make([]byte, 32) - len := d.serializeLevel2Input(buf, drkey.AsHost, d.Proto, host) - outKey, err := drkey.DeriveKey(buf[:len], key) + l, err := d.serializeLevel2Input(buf, drkey.AsHost, d.Proto, host) + if err != nil { + return drkey.Key{}, serrors.WrapStr("serializing drkey level 2 input", err) + } + outKey, err := drkey.DeriveKey(buf[:l], key) return outKey, err } @@ -48,13 +53,16 @@ func (d Deriver) DeriveHostAS( key drkey.Key, ) (drkey.Key, error) { - host, err := drkey.HostAddrFromString(srcHost) + host, err := addr.ParseHost(srcHost) if err != nil { return drkey.Key{}, serrors.WrapStr("parsing src host", err) } buf := make([]byte, 32) - len := d.serializeLevel2Input(buf, drkey.HostAS, d.Proto, host) - outKey, err := drkey.DeriveKey(buf[:len], key) + l, err := d.serializeLevel2Input(buf, drkey.HostAS, d.Proto, host) + if err != nil { + return drkey.Key{}, serrors.WrapStr("serializing drkey level 2 input", err) + } + outKey, err := drkey.DeriveKey(buf[:l], key) return outKey, err } @@ -64,13 +72,16 @@ func (d Deriver) DeriveHostHost( key drkey.Key, ) (drkey.Key, error) { - host, err := drkey.HostAddrFromString(dstHost) + host, err := addr.ParseHost(dstHost) if err != nil { return drkey.Key{}, serrors.WrapStr("deriving input H2H", err) } buf := make([]byte, 32) - len := drkey.SerializeHostHostInput(buf[:], host) - outKey, err := drkey.DeriveKey(buf[:len], key) + l, err := drkey.SerializeHostHostInput(buf[:], host) + if err != nil { + return drkey.Key{}, serrors.WrapStr("serializing drkey host-host input", err) + } + outKey, err := drkey.DeriveKey(buf[:l], key) return outKey, err } @@ -81,11 +92,14 @@ func (d Deriver) serializeLevel2Input( input []byte, derType drkey.KeyType, proto drkey.Protocol, - host drkey.HostAddr, -) int { + host addr.Host, +) (int, error) { - hostAddr := host.RawAddr - l := len(hostAddr) + typ, raw, err := slayers.PackAddr(host) + if err != nil { + return 0, serrors.WrapStr("packing host address", err) + } + l := len(raw) // Calculate a multiple of 16 such that the input fits in nrBlocks := (4+l-1)/16 + 1 @@ -94,9 +108,9 @@ func (d Deriver) serializeLevel2Input( _ = input[inputLength-1] input[0] = uint8(derType) binary.BigEndian.PutUint16(input[1:], uint16(proto)) - input[3] = uint8(host.AddrType & 0xF) - copy(input[4:], hostAddr) + input[3] = uint8(typ & 0xF) + copy(input[4:], raw) copy(input[4+l:inputLength], drkey.ZeroBlock[:]) - return inputLength + return inputLength, nil } diff --git a/pkg/drkey/protocol.go b/pkg/drkey/protocol.go index ee3fa596c..b9469c0c8 100644 --- a/pkg/drkey/protocol.go +++ b/pkg/drkey/protocol.go @@ -17,8 +17,6 @@ package drkey import ( "crypto/aes" "crypto/cipher" - "encoding/binary" - "net" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/serrors" @@ -40,60 +38,16 @@ var ( ZeroBlock [aes.BlockSize]byte ) -// HostAddr is the address representation of a host as defined in the SCION header. -type HostAddr struct { - AddrType slayers.AddrType - RawAddr []byte -} - -// AddrToString returns the string representation of the HostAddr. -func (h *HostAddr) String() string { - switch h.AddrType { - case slayers.T4Ip: - return net.IP(h.RawAddr).String() - case slayers.T4Svc: - addr := addr.HostSVC(binary.BigEndian.Uint16(h.RawAddr[:addr.HostLenSVC])) - return addr.String() - case slayers.T16Ip: - return net.IP(h.RawAddr).String() - } - return "" -} - -// packtoHostAddr returns a HostAddr parsing a given address in string format. -func HostAddrFromString(host string) (HostAddr, error) { - // trying IP - ipAddr := addr.HostFromIPStr(host) - if ipAddr != nil { - if ip := ipAddr.IP().To4(); ip != nil { - return HostAddr{ - AddrType: slayers.T4Ip, - RawAddr: ip, - }, nil - } - return HostAddr{ - AddrType: slayers.T16Ip, - RawAddr: ipAddr.IP(), - }, nil - } - // trying SVC - svcAddr := addr.HostSVCFromString(host) - if svcAddr != addr.SvcNone { - return HostAddr{ - AddrType: slayers.T4Svc, - RawAddr: svcAddr.PackWithPad(2), - }, nil - } - return HostAddr{}, serrors.New("unsupported address", "addr", host) -} - // SerializeHostHostInput serializes the input for deriving a HostHost key, // as explained in // https://docs.scion.org/en/latest/cryptography/drkey.html#level-derivation. // This derivation is common for Generic and Specific derivations. -func SerializeHostHostInput(input []byte, host HostAddr) int { - hostAddr := host.RawAddr - l := len(hostAddr) +func SerializeHostHostInput(input []byte, host addr.Host) (int, error) { + typ, raw, err := slayers.PackAddr(host) + if err != nil { + return 0, serrors.WrapStr("packing host address", err) + } + l := len(raw) // Calculate a multiple of 16 such that the input fits in nrBlocks := (2+l-1)/16 + 1 @@ -102,11 +56,11 @@ func SerializeHostHostInput(input []byte, host HostAddr) int { _ = input[inputLength-1] input[0] = uint8(HostHost) - input[1] = uint8(host.AddrType & 0xF) - copy(input[2:], hostAddr) + input[1] = uint8(typ & 0xF) + copy(input[2:], raw) copy(input[2+l:inputLength], ZeroBlock[:]) - return inputLength + return inputLength, nil } // DeriveKey derives the following key given an input and a higher-level key, diff --git a/pkg/drkey/specific/BUILD.bazel b/pkg/drkey/specific/BUILD.bazel index c3316a6a9..baad2183a 100644 --- a/pkg/drkey/specific/BUILD.bazel +++ b/pkg/drkey/specific/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "//pkg/addr:go_default_library", "//pkg/drkey:go_default_library", "//pkg/private/serrors:go_default_library", + "//pkg/slayers:go_default_library", ], ) diff --git a/pkg/drkey/specific/specific.go b/pkg/drkey/specific/specific.go index b156b2f6c..88a585a28 100644 --- a/pkg/drkey/specific/specific.go +++ b/pkg/drkey/specific/specific.go @@ -21,6 +21,7 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/slayers" ) // SpecificDeriver implements the specific drkey derivation. @@ -44,37 +45,46 @@ func (d Deriver) DeriveASHost( key drkey.Key, ) (drkey.Key, error) { - host, err := drkey.HostAddrFromString(dstHost) + host, err := addr.ParseHost(dstHost) if err != nil { return drkey.Key{}, serrors.WrapStr("parsing dst host", err) } buf := make([]byte, 32) - len := d.serializeLevel2Input(buf, drkey.AsHost, host) - outKey, err := drkey.DeriveKey(buf[:len], key) + l, err := d.serializeLevel2Input(buf, drkey.AsHost, host) + if err != nil { + return drkey.Key{}, serrors.WrapStr("serializing drkey level 2 input", err) + } + outKey, err := drkey.DeriveKey(buf[:l], key) return outKey, err } // DeriveHostAS returns the HostAS derived key. func (p Deriver) DeriveHostAS(srcHost string, key drkey.Key) (drkey.Key, error) { - host, err := drkey.HostAddrFromString(srcHost) + host, err := addr.ParseHost(srcHost) if err != nil { return drkey.Key{}, serrors.WrapStr("parsing src host", err) } buf := make([]byte, 32) - len := p.serializeLevel2Input(buf, drkey.HostAS, host) - outKey, err := drkey.DeriveKey(buf[:len], key) + l, err := p.serializeLevel2Input(buf, drkey.HostAS, host) + if err != nil { + return drkey.Key{}, serrors.WrapStr("serializing drkey level 2 input", err) + } + outKey, err := drkey.DeriveKey(buf[:l], key) return outKey, err } // DeriveHostHost returns the HostHost derived key. func (d Deriver) DeriveHostHost(dstHost string, key drkey.Key) (drkey.Key, error) { - host, err := drkey.HostAddrFromString(dstHost) + host, err := addr.ParseHost(dstHost) if err != nil { return drkey.Key{}, serrors.WrapStr("deriving input H2H", err) } buf := make([]byte, 32) - len := drkey.SerializeHostHostInput(buf, host) - outKey, err := drkey.DeriveKey(buf[:len], key) + l, err := drkey.SerializeHostHostInput(buf, host) + if err != nil { + return drkey.Key{}, serrors.WrapStr("serializing drkey host-host input", err) + } + outKey, err := drkey.DeriveKey(buf[:l], key) return outKey, err } @@ -84,11 +94,14 @@ func (d Deriver) DeriveHostHost(dstHost string, key drkey.Key) (drkey.Key, error func (d Deriver) serializeLevel2Input( input []byte, derType drkey.KeyType, - host drkey.HostAddr, -) int { + host addr.Host, +) (int, error) { - hostAddr := host.RawAddr - l := len(hostAddr) + typ, raw, err := slayers.PackAddr(host) + if err != nil { + return 0, serrors.WrapStr("packing host address", err) + } + l := len(raw) // Calculate a multiple of 16 such that the input fits in nrBlocks := (2+l-1)/16 + 1 @@ -96,11 +109,11 @@ func (d Deriver) serializeLevel2Input( _ = input[inputLength-1] input[0] = uint8(derType) - input[1] = uint8(host.AddrType & 0xF) - copy(input[2:], hostAddr) + input[1] = uint8(typ & 0xF) + copy(input[2:], raw) copy(input[2+l:inputLength], drkey.ZeroBlock[:]) - return inputLength + return inputLength, nil } // serializeLevel1Input serializes the input for a Level1 key, diff --git a/pkg/experimental/epic/BUILD.bazel b/pkg/experimental/epic/BUILD.bazel index 753ce3b34..15dc154e9 100644 --- a/pkg/experimental/epic/BUILD.bazel +++ b/pkg/experimental/epic/BUILD.bazel @@ -24,6 +24,7 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//pkg/addr:go_default_library", "//pkg/private/xtest:go_default_library", "//pkg/slayers:go_default_library", "//pkg/slayers/path/epic:go_default_library", diff --git a/pkg/experimental/epic/epic_test.go b/pkg/experimental/epic/epic_test.go index 6de95ac23..6d7bb3284 100644 --- a/pkg/experimental/epic/epic_test.go +++ b/pkg/experimental/epic/epic_test.go @@ -15,13 +15,13 @@ package epic_test import ( - "net" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/scionproto/scion/pkg/addr" libepic "github.com/scionproto/scion/pkg/experimental/epic" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -384,8 +384,7 @@ func createScionCmnAddrHdr(t *testing.T) *slayers.SCION { SrcIA: xtest.MustParseIA("2-ff00:0:222"), PayloadLen: 120, } - ip4Addr := &net.IPAddr{IP: net.ParseIP("10.0.0.100")} - require.NoError(t, spkt.SetSrcAddr(ip4Addr)) + _ = spkt.SetSrcAddr(addr.MustParseHost("10.0.0.100")) return spkt } diff --git a/pkg/experimental/hiddenpath/beaconwriter_test.go b/pkg/experimental/hiddenpath/beaconwriter_test.go index 95c089107..3cd383fa2 100644 --- a/pkg/experimental/hiddenpath/beaconwriter_test.go +++ b/pkg/experimental/hiddenpath/beaconwriter_test.go @@ -308,7 +308,7 @@ func (m addrMatcher) Matches(other interface{}) bool { if !m.svc.IA.Equal(svc.IA) { return false } - if !m.svc.SVC.Equal(svc.SVC) { + if m.svc.SVC != svc.SVC { return false } return true diff --git a/pkg/grpc/BUILD.bazel b/pkg/grpc/BUILD.bazel index fc6a2b1c4..e82853d5f 100644 --- a/pkg/grpc/BUILD.bazel +++ b/pkg/grpc/BUILD.bazel @@ -33,6 +33,7 @@ go_test( deps = [ ":go_default_library", "//pkg/addr:go_default_library", + "//pkg/snet:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", "@org_golang_google_grpc//:go_default_library", diff --git a/pkg/grpc/dialer.go b/pkg/grpc/dialer.go index 952870036..03edee33a 100644 --- a/pkg/grpc/dialer.go +++ b/pkg/grpc/dialer.go @@ -90,20 +90,21 @@ func (SimpleDialer) Dial(ctx context.Context, address net.Addr) (*grpc.ClientCon // TCPDialer dials a gRPC connection over TCP. This dialer is meant to be used // for AS internal communication, and is capable of resolving svc addresses. type TCPDialer struct { - SvcResolver func(addr.HostSVC) []resolver.Address + SvcResolver func(addr.SVC) []resolver.Address } // Dial dials a gRPC connection over TCP. It resolves svc addresses. func (t *TCPDialer) Dial(ctx context.Context, dst net.Addr) (*grpc.ClientConn, error) { - if v, ok := dst.(addr.HostSVC); ok { - targets := t.SvcResolver(v) + if v, ok := dst.(*snet.SVCAddr); ok { + // XXX(matzf) is this really needed!? + targets := t.SvcResolver(v.SVC) if len(targets) == 0 { return nil, serrors.New("could not resolve") } r := manual.NewBuilderWithScheme("svc") r.InitialState(resolver.State{Addresses: targets}) - return grpc.DialContext(ctx, r.Scheme()+":///"+v.BaseString(), + return grpc.DialContext(ctx, r.Scheme()+":///"+v.SVC.BaseString(), grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin":{}}]}`), grpc.WithInsecure(), grpc.WithResolvers(r), diff --git a/pkg/grpc/dialer_test.go b/pkg/grpc/dialer_test.go index 533f92ebd..0c6260525 100644 --- a/pkg/grpc/dialer_test.go +++ b/pkg/grpc/dialer_test.go @@ -31,6 +31,7 @@ import ( "github.com/scionproto/scion/pkg/addr" libgrpc "github.com/scionproto/scion/pkg/grpc" + "github.com/scionproto/scion/pkg/snet" ) func TestTCPDial(t *testing.T) { @@ -62,22 +63,22 @@ func TestTCPDial(t *testing.T) { t.Run("cases", func(t *testing.T) { testCases := map[string]struct { - svcResolve func(*testing.T, addr.HostSVC) []resolver.Address + svcResolve func(*testing.T, addr.SVC) []resolver.Address dst net.Addr assertDialError assert.ErrorAssertionFunc assertCallError assert.ErrorAssertionFunc }{ "valid tcp address": { dst: lis.Addr(), - svcResolve: func(*testing.T, addr.HostSVC) []resolver.Address { + svcResolve: func(*testing.T, addr.SVC) []resolver.Address { return nil }, assertDialError: assert.NoError, assertCallError: assert.NoError, }, "valid cs svc address": { - dst: addr.SvcCS, - svcResolve: func(*testing.T, addr.HostSVC) []resolver.Address { + dst: &snet.SVCAddr{SVC: addr.SvcCS}, + svcResolve: func(*testing.T, addr.SVC) []resolver.Address { return []resolver.Address{ {Addr: lis.Addr().String()}, {Addr: getUnusedAddr(t)}, @@ -87,8 +88,8 @@ func TestTCPDial(t *testing.T) { assertCallError: assert.NoError, }, "valid cs svc address second": { - dst: addr.SvcCS, - svcResolve: func(*testing.T, addr.HostSVC) []resolver.Address { + dst: &snet.SVCAddr{SVC: addr.SvcCS}, + svcResolve: func(*testing.T, addr.SVC) []resolver.Address { return []resolver.Address{ {Addr: getUnusedAddr(t)}, {Addr: lis.Addr().String()}, @@ -98,8 +99,8 @@ func TestTCPDial(t *testing.T) { assertCallError: assert.NoError, }, "valid, one server with no gRPC": { - dst: addr.SvcCS, - svcResolve: func(*testing.T, addr.HostSVC) []resolver.Address { + dst: &snet.SVCAddr{SVC: addr.SvcCS}, + svcResolve: func(*testing.T, addr.SVC) []resolver.Address { return []resolver.Address{ {Addr: noGRPCLis.Addr().String()}, {Addr: lis.Addr().String()}, @@ -109,8 +110,8 @@ func TestTCPDial(t *testing.T) { assertCallError: assert.NoError, }, "invalid": { - dst: addr.SvcCS, - svcResolve: func(*testing.T, addr.HostSVC) []resolver.Address { + dst: &snet.SVCAddr{SVC: addr.SvcCS}, + svcResolve: func(*testing.T, addr.SVC) []resolver.Address { return nil }, assertDialError: assert.Error, @@ -131,7 +132,7 @@ func TestTCPDial(t *testing.T) { defer cancel() dialer := libgrpc.TCPDialer{ - SvcResolver: func(svc addr.HostSVC) []resolver.Address { + SvcResolver: func(svc addr.SVC) []resolver.Address { return tc.svcResolve(t, svc) }, } diff --git a/pkg/slayers/export_test.go b/pkg/slayers/export_test.go index dcdec7a7d..8897b970f 100644 --- a/pkg/slayers/export_test.go +++ b/pkg/slayers/export_test.go @@ -19,8 +19,6 @@ package slayers type TLVOption = tlvOption var ( - PackAddr = packAddr - ParseAddr = parseAddr SerializeTLVOptions = serializeTLVOptions ) diff --git a/pkg/slayers/scion.go b/pkg/slayers/scion.go index 86343d758..7e24772f1 100644 --- a/pkg/slayers/scion.go +++ b/pkg/slayers/scion.go @@ -16,7 +16,7 @@ package slayers import ( "encoding/binary" - "net" + "net/netip" "github.com/google/gopacket" @@ -349,64 +349,66 @@ func scionNextLayerTypeL4(t L4ProtocolType) gopacket.LayerType { } } -// DstAddr parses the destination address into a net.Addr. The returned net.Addr references data -// from the underlaying layer data. Changing the net.Addr object might lead to inconsistent layer -// information and thus should be treated read-only. Instead, SetDstAddr should be used to update -// the destination address. -func (s *SCION) DstAddr() (net.Addr, error) { - return parseAddr(s.DstAddrType, s.RawDstAddr) +// DstAddr parses the destination address into a addr.Host. +func (s *SCION) DstAddr() (addr.Host, error) { + return ParseAddr(s.DstAddrType, s.RawDstAddr) } -// SrcAddr parses the source address into a net.Addr. The returned net.Addr references data from the -// underlaying layer data. Changing the net.Addr object might lead to inconsistent layer information -// and thus should be treated read-only. Instead, SetDstAddr should be used to update the source -// address. -func (s *SCION) SrcAddr() (net.Addr, error) { - return parseAddr(s.SrcAddrType, s.RawSrcAddr) +// SrcAddr parses the source address into a addr.Host. +func (s *SCION) SrcAddr() (addr.Host, error) { + return ParseAddr(s.SrcAddrType, s.RawSrcAddr) } // SetDstAddr sets the destination address and updates the DstAddrType field accordingly. -// SetDstAddr takes ownership of dst and callers should not write to it after calling SetDstAddr. -// Changes to dst might leave the layer in an inconsistent state. -func (s *SCION) SetDstAddr(dst net.Addr) error { +func (s *SCION) SetDstAddr(dst addr.Host) error { var err error - s.DstAddrType, s.RawDstAddr, err = packAddr(dst) + s.DstAddrType, s.RawDstAddr, err = PackAddr(dst) return err } // SetSrcAddr sets the source address and updates the DstAddrType field accordingly. -// SetSrcAddr takes ownership of src and callers should not write to it after calling SetSrcAddr. -// Changes to src might leave the layer in an inconsistent state. -func (s *SCION) SetSrcAddr(src net.Addr) error { +func (s *SCION) SetSrcAddr(src addr.Host) error { var err error - s.SrcAddrType, s.RawSrcAddr, err = packAddr(src) + s.SrcAddrType, s.RawSrcAddr, err = PackAddr(src) return err } -func parseAddr(addrType AddrType, raw []byte) (net.Addr, error) { +func ParseAddr(addrType AddrType, raw []byte) (addr.Host, error) { switch addrType { case T4Ip: - return &net.IPAddr{IP: net.IP(raw)}, nil + var raw4 [4]byte + copy(raw4[:], raw) + return addr.HostIP(netip.AddrFrom4(raw4)), nil case T4Svc: - return addr.HostSVC(binary.BigEndian.Uint16(raw[:addr.HostLenSVC])), nil + svc := addr.SVC(binary.BigEndian.Uint16(raw[:2])) + return addr.HostSVC(svc), nil case T16Ip: - return &net.IPAddr{IP: net.IP(raw)}, nil + var raw16 [16]byte + copy(raw16[:], raw) + return addr.HostIP(netip.AddrFrom16(raw16)), nil } - return nil, serrors.New("unsupported address type/length combination", + return addr.Host{}, serrors.New("unsupported address type/length combination", "type", addrType, "len", addrType.Length()) } -func packAddr(hostAddr net.Addr) (AddrType, []byte, error) { - switch a := hostAddr.(type) { - case *net.IPAddr: - if ip := a.IP.To4(); ip != nil { - return T4Ip, ip, nil +func PackAddr(host addr.Host) (AddrType, []byte, error) { + switch host.Type() { + case addr.HostTypeIP: + ip := host.IP() + if !ip.IsValid() { + break } - return T16Ip, a.IP, nil - case addr.HostSVC: - return T4Svc, a.PackWithPad(2), nil + t := T4Ip + if ip.Is6() { + t = T16Ip + } + return t, ip.AsSlice(), nil + case addr.HostTypeSVC: + raw := make([]byte, 4) + binary.BigEndian.PutUint16(raw, uint16(host.SVC())) + return T4Svc, raw, nil } - return 0, nil, serrors.New("unsupported address", "addr", hostAddr) + return 0, nil, serrors.New("unsupported address", "addr", host) } // AddrHdrLen returns the length of the address header (destination and source ISD-AS-Host triples) diff --git a/pkg/slayers/scion_test.go b/pkg/slayers/scion_test.go index 4ee604668..06d496755 100644 --- a/pkg/slayers/scion_test.go +++ b/pkg/slayers/scion_test.go @@ -17,7 +17,6 @@ package slayers_test import ( "encoding/binary" "fmt" - "net" "testing" "github.com/google/gopacket" @@ -34,9 +33,9 @@ import ( ) var ( - ip6Addr = &net.IPAddr{IP: net.ParseIP("2001:db8::68")} - ip4Addr = &net.IPAddr{IP: net.ParseIP("10.0.0.100").To4()} - svcAddr = addr.HostSVCFromString("Wildcard") + ip6Addr = addr.MustParseHost("2001:db8::68") + ip4Addr = addr.MustParseHost("10.0.0.100") + svcAddr = addr.MustParseHost("Wildcard") rawPath = func() []byte { return []byte("\x00\x00\x20\x80\x00\x00\x01\x11\x00\x00\x01\x00\x01\x00\x02\x22\x00" + "\x00\x01\x00\x00\x3f\x00\x01\x00\x00\x01\x02\x03\x04\x05\x06\x00\x3f\x00\x03\x00" + @@ -57,10 +56,10 @@ func TestSCIONLayerString(t *testing.T) { DstIA: ia1, SrcIA: ia2, } - if err := sc.SetDstAddr(&net.IPAddr{IP: net.ParseIP("1.2.3.4").To4()}); err != nil { + if err := sc.SetDstAddr(addr.MustParseHost("1.2.3.4")); err != nil { assert.NoError(t, err) } - if err := sc.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("5.6.7.8").To4()}); err != nil { + if err := sc.SetSrcAddr(addr.MustParseHost("5.6.7.8")); err != nil { assert.NoError(t, err) } @@ -256,8 +255,8 @@ func TestSCIONSerializeLengthCheck(t *testing.T) { func TestSetAndGetAddr(t *testing.T) { testCases := map[string]struct { - srcAddr net.Addr - dstAddr net.Addr + srcAddr addr.Host + dstAddr addr.Host }{ "set/get IPv4/IPv4": { srcAddr: ip4Addr, @@ -293,22 +292,15 @@ func TestSetAndGetAddr(t *testing.T) { gotDst, err := s.DstAddr() assert.NoError(t, err) - equalAddr := func(t *testing.T, expected, actual net.Addr) { - if _, ok := expected.(*net.IPAddr); !ok { - assert.Equal(t, expected, actual) - return - } - assert.True(t, expected.(*net.IPAddr).IP.Equal(actual.(*net.IPAddr).IP)) - } - equalAddr(t, tc.srcAddr, gotSrc) - equalAddr(t, tc.dstAddr, gotDst) + assert.Equal(t, tc.srcAddr, gotSrc) + assert.Equal(t, tc.dstAddr, gotDst) }) } } func TestPackAddr(t *testing.T) { testCases := map[string]struct { - addr net.Addr + addr addr.Host addrType slayers.AddrType rawAddr []byte errorFunc assert.ErrorAssertionFunc @@ -316,19 +308,19 @@ func TestPackAddr(t *testing.T) { "pack IPv4": { addr: ip4Addr, addrType: slayers.T4Ip, - rawAddr: []byte(ip4Addr.IP), + rawAddr: ip4Addr.IP().AsSlice(), errorFunc: assert.NoError, }, "pack IPv6": { addr: ip6Addr, addrType: slayers.T16Ip, - rawAddr: []byte(ip6Addr.IP), + rawAddr: ip6Addr.IP().AsSlice(), errorFunc: assert.NoError, }, "pack SVC": { - addr: svcAddr, + addr: addr.HostSVC(addr.SvcWildcard), addrType: slayers.T4Svc, - rawAddr: svcAddr.PackWithPad(2), + rawAddr: []byte{0, 0x10, 0, 0}, errorFunc: assert.NoError, }, } @@ -350,31 +342,31 @@ func TestParseAddr(t *testing.T) { testCases := map[string]struct { addrType slayers.AddrType rawAddr []byte - want net.Addr + want addr.Host errorFunc assert.ErrorAssertionFunc }{ "parse IPv4": { addrType: slayers.T4Ip, - rawAddr: []byte(ip4Addr.IP.To4()), + rawAddr: ip4Addr.IP().AsSlice(), want: ip4Addr, errorFunc: assert.NoError, }, "parse IPv6": { addrType: slayers.T16Ip, - rawAddr: []byte(ip6Addr.IP), + rawAddr: ip6Addr.IP().AsSlice(), want: ip6Addr, errorFunc: assert.NoError, }, "parse SVC": { addrType: slayers.T4Svc, - rawAddr: svcAddr.PackWithPad(2), - want: svcAddr, + rawAddr: []byte{0, 0x10, 0, 0}, + want: addr.HostSVC(addr.SvcWildcard), errorFunc: assert.NoError, }, "parse unknown type": { addrType: 0b0001, // T=0,Len=8 rawAddr: []byte{0, 0, 0, 0, 0, 0, 0, 0}, - want: nil, + want: addr.Host{}, errorFunc: assert.Error, }, } @@ -547,9 +539,9 @@ func TestSCIONComputeChecksum(t *testing.T) { SrcIA: xtest.MustParseIA("1-ff00:0:110"), DstIA: xtest.MustParseIA("1-ff00:0:112"), } - err := s.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}) + err := s.SetSrcAddr(addr.MustParseHost("174.16.4.1")) require.NoError(t, err) - err = s.SetDstAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.2").To4()}) + err = s.SetDstAddr(addr.MustParseHost("172.16.4.2")) require.NoError(t, err) return s }, @@ -563,9 +555,9 @@ func TestSCIONComputeChecksum(t *testing.T) { SrcIA: xtest.MustParseIA("1-ff00:0:110"), DstIA: xtest.MustParseIA("1-ff00:0:112"), } - err := s.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}) + err := s.SetSrcAddr(addr.MustParseHost("174.16.4.1")) require.NoError(t, err) - err = s.SetDstAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.2").To4()}) + err = s.SetDstAddr(addr.MustParseHost("172.16.4.2")) require.NoError(t, err) return s }, @@ -579,9 +571,9 @@ func TestSCIONComputeChecksum(t *testing.T) { SrcIA: xtest.MustParseIA("1-ff00:0:110"), DstIA: xtest.MustParseIA("1-ff00:0:112"), } - err := s.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}) + err := s.SetSrcAddr(addr.MustParseHost("174.16.4.1")) require.NoError(t, err) - err = s.SetDstAddr(&net.IPAddr{IP: net.ParseIP("dead::beef")}) + err = s.SetDstAddr(addr.MustParseHost("dead::beef")) require.NoError(t, err) return s }, @@ -595,9 +587,9 @@ func TestSCIONComputeChecksum(t *testing.T) { SrcIA: xtest.MustParseIA("1-ff00:0:110"), DstIA: xtest.MustParseIA("1-ff00:0:112"), } - err := s.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}) + err := s.SetSrcAddr(addr.MustParseHost("174.16.4.1")) require.NoError(t, err) - err = s.SetDstAddr(addr.SvcCS) + err = s.SetDstAddr(addr.HostSVC(addr.SvcCS)) require.NoError(t, err) return s }, diff --git a/pkg/slayers/scmp_test.go b/pkg/slayers/scmp_test.go index c8881e8d9..dfeceb54f 100644 --- a/pkg/slayers/scmp_test.go +++ b/pkg/slayers/scmp_test.go @@ -17,13 +17,13 @@ package slayers_test import ( "bytes" "fmt" - "net" "testing" "github.com/google/gopacket" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" ) @@ -82,9 +82,9 @@ func TestSCMPSerializeTo(t *testing.T) { SrcIA: xtest.MustParseIA("1-ff00:0:1"), DstIA: xtest.MustParseIA("1-ff00:0:4"), } - err := scnL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}) + err := scnL.SetDstAddr(addr.MustParseHost("174.16.4.1")) require.NoError(t, err) - err = scnL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.3")}) + err = scnL.SetSrcAddr(addr.MustParseHost("172.16.4.3")) require.NoError(t, err) testCases := map[string]struct { @@ -513,9 +513,9 @@ func TestSCMP(t *testing.T) { SrcIA: xtest.MustParseIA("1-ff00:0:1"), DstIA: xtest.MustParseIA("1-ff00:0:4"), } - err := scnL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}) + err := scnL.SetDstAddr(addr.MustParseHost("174.16.4.1")) assert.NoError(t, err) - err = scnL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.3").To4()}) + err = scnL.SetSrcAddr(addr.MustParseHost("172.16.4.3")) require.NoError(t, err) opts := gopacket.SerializeOptions{ComputeChecksums: true} diff --git a/pkg/snet/addrutil/addrutil.go b/pkg/snet/addrutil/addrutil.go index 60595f91b..aa6e65c27 100644 --- a/pkg/snet/addrutil/addrutil.go +++ b/pkg/snet/addrutil/addrutil.go @@ -40,7 +40,7 @@ type Pather struct { } // GetPath computes the remote address with a path based on the provided segment. -func (p Pather) GetPath(svc addr.HostSVC, ps *seg.PathSegment) (*snet.SVCAddr, error) { +func (p Pather) GetPath(svc addr.SVC, ps *seg.PathSegment) (*snet.SVCAddr, error) { if len(ps.ASEntries) == 0 { return nil, serrors.New("empty path") } diff --git a/pkg/snet/base.go b/pkg/snet/base.go index 2d7c84fc7..a06f956f0 100644 --- a/pkg/snet/base.go +++ b/pkg/snet/base.go @@ -27,7 +27,7 @@ type scionConnBase struct { remote *UDPAddr // svc address - svc addr.HostSVC + svc addr.SVC // Reference to SCION networking context scionNet *SCIONNetwork @@ -41,6 +41,6 @@ func (c *scionConnBase) RemoteAddr() net.Addr { return c.remote } -func (c *scionConnBase) SVC() addr.HostSVC { +func (c *scionConnBase) SVC() addr.SVC { return c.svc } diff --git a/pkg/snet/dispatcher.go b/pkg/snet/dispatcher.go index 8e1e6c87d..bfc1180a0 100644 --- a/pkg/snet/dispatcher.go +++ b/pkg/snet/dispatcher.go @@ -34,7 +34,7 @@ import ( // fine-grained control over header fields. type PacketDispatcherService interface { Register(ctx context.Context, ia addr.IA, registration *net.UDPAddr, - svc addr.HostSVC) (PacketConn, uint16, error) + svc addr.SVC) (PacketConn, uint16, error) } var _ PacketDispatcherService = (*DefaultPacketDispatcherService)(nil) @@ -53,7 +53,7 @@ type DefaultPacketDispatcherService struct { } func (s *DefaultPacketDispatcherService) Register(ctx context.Context, ia addr.IA, - registration *net.UDPAddr, svc addr.HostSVC) (PacketConn, uint16, error) { + registration *net.UDPAddr, svc addr.SVC) (PacketConn, uint16, error) { rconn, port, err := s.Dispatcher.Register(ctx, ia, registration, svc) if err != nil { diff --git a/pkg/snet/interface.go b/pkg/snet/interface.go index 37f704608..343ec1a44 100644 --- a/pkg/snet/interface.go +++ b/pkg/snet/interface.go @@ -24,7 +24,7 @@ import ( type Network interface { Listen(ctx context.Context, network string, listen *net.UDPAddr, - svc addr.HostSVC) (*Conn, error) + svc addr.SVC) (*Conn, error) Dial(ctx context.Context, network string, listen *net.UDPAddr, remote *UDPAddr, - svc addr.HostSVC) (*Conn, error) + svc addr.SVC) (*Conn, error) } diff --git a/pkg/snet/mock_snet/mock.go b/pkg/snet/mock_snet/mock.go index fd52a212c..181ac9a92 100644 --- a/pkg/snet/mock_snet/mock.go +++ b/pkg/snet/mock_snet/mock.go @@ -40,7 +40,7 @@ func (m *MockPacketDispatcherService) EXPECT() *MockPacketDispatcherServiceMockR } // Register mocks base method. -func (m *MockPacketDispatcherService) Register(arg0 context.Context, arg1 addr.IA, arg2 *net.UDPAddr, arg3 addr.HostSVC) (snet.PacketConn, uint16, error) { +func (m *MockPacketDispatcherService) Register(arg0 context.Context, arg1 addr.IA, arg2 *net.UDPAddr, arg3 addr.SVC) (snet.PacketConn, uint16, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Register", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(snet.PacketConn) @@ -79,7 +79,7 @@ func (m *MockNetwork) EXPECT() *MockNetworkMockRecorder { } // Dial mocks base method. -func (m *MockNetwork) Dial(arg0 context.Context, arg1 string, arg2 *net.UDPAddr, arg3 *snet.UDPAddr, arg4 addr.HostSVC) (*snet.Conn, error) { +func (m *MockNetwork) Dial(arg0 context.Context, arg1 string, arg2 *net.UDPAddr, arg3 *snet.UDPAddr, arg4 addr.SVC) (*snet.Conn, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Dial", arg0, arg1, arg2, arg3, arg4) ret0, _ := ret[0].(*snet.Conn) @@ -94,7 +94,7 @@ func (mr *MockNetworkMockRecorder) Dial(arg0, arg1, arg2, arg3, arg4 interface{} } // Listen mocks base method. -func (m *MockNetwork) Listen(arg0 context.Context, arg1 string, arg2 *net.UDPAddr, arg3 addr.HostSVC) (*snet.Conn, error) { +func (m *MockNetwork) Listen(arg0 context.Context, arg1 string, arg2 *net.UDPAddr, arg3 addr.SVC) (*snet.Conn, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Listen", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(*snet.Conn) diff --git a/pkg/snet/packet.go b/pkg/snet/packet.go index 7289cc5d9..6444d34d0 100644 --- a/pkg/snet/packet.go +++ b/pkg/snet/packet.go @@ -15,8 +15,6 @@ package snet import ( - "net" - "github.com/google/gopacket" "github.com/scionproto/scion/pkg/addr" @@ -370,20 +368,12 @@ func (p *Packet) Decode() error { if err != nil { return serrors.WrapStr("extracting destination address", err) } - dstHost, err := netAddrToHostAddr(dstAddr) - if err != nil { - return serrors.WrapStr("converting dst address to HostAddr", err) - } srcAddr, err := scionLayer.SrcAddr() if err != nil { return serrors.WrapStr("extracting source address", err) } - srcHost, err := netAddrToHostAddr(srcAddr) - if err != nil { - return serrors.WrapStr("converting src address to HostAddr", err) - } - p.Destination = SCIONAddress{IA: scionLayer.DstIA, Host: dstHost} - p.Source = SCIONAddress{IA: scionLayer.SrcIA, Host: srcHost} + p.Destination = SCIONAddress{IA: scionLayer.DstIA, Host: dstAddr} + p.Source = SCIONAddress{IA: scionLayer.SrcIA, Host: srcAddr} rpath := RawPath{ PathType: scionLayer.Path.Type(), @@ -549,20 +539,10 @@ func (p *Packet) Serialize() error { scionLayer.FlowID = 1 scionLayer.DstIA = p.Destination.IA scionLayer.SrcIA = p.Source.IA - netDstAddr, err := hostAddrToNetAddr(p.Destination.Host) - if err != nil { - return serrors.WrapStr("converting destination addr.HostAddr to net.Addr", err, - "address", p.Destination.Host) - } - if err := scionLayer.SetDstAddr(netDstAddr); err != nil { + if err := scionLayer.SetDstAddr(p.Destination.Host); err != nil { return serrors.WrapStr("setting destination address", err) } - netSrcAddr, err := hostAddrToNetAddr(p.Source.Host) - if err != nil { - return serrors.WrapStr("converting source addr.HostAddr to net.Addr", err, - "address", p.Source.Host) - } - if err := scionLayer.SetSrcAddr(netSrcAddr); err != nil { + if err := scionLayer.SetSrcAddr(p.Source.Host); err != nil { return serrors.WrapStr("setting source address", err) } @@ -612,25 +592,3 @@ type PacketInfo struct { // Payload is the Payload of the message. Payload Payload } - -func netAddrToHostAddr(a net.Addr) (addr.HostAddr, error) { - switch aImpl := a.(type) { - case *net.IPAddr: - return addr.HostFromIP(aImpl.IP), nil - case addr.HostSVC: - return aImpl, nil - default: - return nil, serrors.New("address not supported", "a", a) - } -} - -func hostAddrToNetAddr(a addr.HostAddr) (net.Addr, error) { - switch aImpl := a.(type) { - case addr.HostSVC: - return aImpl, nil - case addr.HostIPv4, addr.HostIPv6: - return &net.IPAddr{IP: aImpl.IP()}, nil - default: - return nil, serrors.New("address not supported", "a", a) - } -} diff --git a/pkg/snet/packet_conn.go b/pkg/snet/packet_conn.go index 7dfd02748..6e257f309 100644 --- a/pkg/snet/packet_conn.go +++ b/pkg/snet/packet_conn.go @@ -15,7 +15,6 @@ package snet import ( - "fmt" "net" "time" @@ -82,14 +81,7 @@ type SCMPExternalInterfaceDownL4 struct { func (SCMPExternalInterfaceDownL4) closed() {} // SCIONAddress is the fully-specified address of a host. -type SCIONAddress struct { - IA addr.IA - Host addr.HostAddr -} - -func (a SCIONAddress) String() string { - return fmt.Sprintf("%v,%s", a.IA, a.Host.String()) -} +type SCIONAddress = addr.Addr type SCIONPacketConnMetrics struct { // Closes records the total number of Close calls on the connection. diff --git a/pkg/snet/packet_test.go b/pkg/snet/packet_test.go index f0d32ef55..ebaf1f55f 100644 --- a/pkg/snet/packet_test.go +++ b/pkg/snet/packet_test.go @@ -15,7 +15,6 @@ package snet_test import ( - "net" "testing" "github.com/stretchr/testify/assert" @@ -55,11 +54,11 @@ func TestPacketSerializeDecodeLoop(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1").To4()), + Host: addr.MustParseHost("127.0.0.1"), }, Path: snetpath.OneHop{}, Payload: snet.UDPPayload{ @@ -73,11 +72,11 @@ func TestPacketSerializeDecodeLoop(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1").To4()), + Host: addr.MustParseHost("127.0.0.1"), }, Path: snetpath.SCION{ Raw: rawSP(), @@ -93,11 +92,11 @@ func TestPacketSerializeDecodeLoop(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1").To4()), + Host: addr.MustParseHost("127.0.0.1"), }, Path: snetpath.SCION{ Raw: rawSP(), @@ -113,11 +112,11 @@ func TestPacketSerializeDecodeLoop(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1").To4()), + Host: addr.MustParseHost("127.0.0.1"), }, Path: snetpath.SCION{ Raw: rawSP(), @@ -133,11 +132,11 @@ func TestPacketSerializeDecodeLoop(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1").To4()), + Host: addr.MustParseHost("127.0.0.1"), }, Path: snetpath.SCION{ Raw: rawSP(), @@ -153,11 +152,11 @@ func TestPacketSerializeDecodeLoop(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1").To4()), + Host: addr.MustParseHost("127.0.0.1"), }, Path: snetpath.SCION{ Raw: rawSP(), @@ -174,11 +173,11 @@ func TestPacketSerializeDecodeLoop(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1").To4()), + Host: addr.MustParseHost("127.0.0.1"), }, Path: snetpath.SCION{ Raw: rawSP(), @@ -196,11 +195,11 @@ func TestPacketSerializeDecodeLoop(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1").To4()), + Host: addr.MustParseHost("127.0.0.1"), }, Path: snetpath.SCION{ Raw: rawSP(), @@ -268,11 +267,11 @@ func TestPacketSerialize(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1")), + Host: addr.MustParseHost("127.0.0.1"), }, Path: snetpath.OneHop{}, Payload: snet.UDPPayload{ @@ -289,11 +288,11 @@ func TestPacketSerialize(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1")), + Host: addr.MustParseHost("127.0.0.1"), }, Payload: snet.UDPPayload{ SrcPort: 25, @@ -313,11 +312,11 @@ func TestPacketSerialize(t *testing.T) { PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:110"), - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), }, Source: snet.SCIONAddress{ IA: xtest.MustParseIA("1-ff00:0:112"), - Host: addr.HostIPv4(net.ParseIP("127.0.0.1")), + Host: addr.MustParseHost("127.0.0.1"), }, Path: snetpath.OneHop{}, }, diff --git a/pkg/snet/reader.go b/pkg/snet/reader.go index ca4b87dde..d09ff6926 100644 --- a/pkg/snet/reader.go +++ b/pkg/snet/reader.go @@ -97,10 +97,10 @@ func (c *scionConnReader) read(b []byte) (int, *UDPAddr, error) { // https://github.com/scionproto/scion/issues/1659. remote := &UDPAddr{ IA: pkt.Source.IA, - Host: CopyUDPAddr(&net.UDPAddr{ - IP: pkt.Source.Host.IP(), + Host: &net.UDPAddr{ + IP: pkt.Source.Host.IP().AsSlice(), Port: int(udp.SrcPort), - }), + }, Path: replyPath, NextHop: CopyUDPAddr(&lastHop), } diff --git a/pkg/snet/snet.go b/pkg/snet/snet.go index e85d2cd4b..c41c269e8 100644 --- a/pkg/snet/snet.go +++ b/pkg/snet/snet.go @@ -82,7 +82,7 @@ type SCIONNetwork struct { // The context is used for connection setup, it doesn't affect the returned // connection. func (n *SCIONNetwork) Dial(ctx context.Context, network string, listen *net.UDPAddr, - remote *UDPAddr, svc addr.HostSVC) (*Conn, error) { + remote *UDPAddr, svc addr.SVC) (*Conn, error) { metrics.CounterInc(n.Metrics.Dials) if remote == nil { @@ -104,7 +104,7 @@ func (n *SCIONNetwork) Dial(ctx context.Context, network string, listen *net.UDP // The context is used for connection setup, it doesn't affect the returned // connection. func (n *SCIONNetwork) Listen(ctx context.Context, network string, listen *net.UDPAddr, - svc addr.HostSVC) (*Conn, error) { + svc addr.SVC) (*Conn, error) { metrics.CounterInc(n.Metrics.Listens) diff --git a/pkg/snet/svcaddr.go b/pkg/snet/svcaddr.go index c65190315..b072cd4c4 100644 --- a/pkg/snet/svcaddr.go +++ b/pkg/snet/svcaddr.go @@ -26,7 +26,7 @@ type SVCAddr struct { IA addr.IA Path DataplanePath NextHop *net.UDPAddr - SVC addr.HostSVC + SVC addr.SVC } // Network implements net.Addr interface. diff --git a/pkg/snet/svcaddr_test.go b/pkg/snet/svcaddr_test.go index 138ec0204..1738fe5fe 100644 --- a/pkg/snet/svcaddr_test.go +++ b/pkg/snet/svcaddr_test.go @@ -36,7 +36,7 @@ func TestSVCAddrString(t *testing.T) { }{ "nil": { input: &snet.SVCAddr{}, - want: "0-0,UNKNOWN A (0x0000)", + want: "0-0,", }, } for n, tc := range tests { diff --git a/pkg/snet/udpaddr.go b/pkg/snet/udpaddr.go index 6d741fea7..50a13cb8c 100644 --- a/pkg/snet/udpaddr.go +++ b/pkg/snet/udpaddr.go @@ -19,7 +19,6 @@ import ( "net" "net/netip" "regexp" - "strconv" "strings" "github.com/scionproto/scion/pkg/addr" @@ -52,34 +51,17 @@ func ParseUDPAddr(s string) (*UDPAddr, error) { // - [isd-as,ipv4]:port (e.g., [1-ff00:0:110,192.0.2.1]:80) // - [isd-as,ipv6%zone]:port (e.g., [1-ff00:0:110,2001:DB8::1%zone]:80) func parseUDPAddr(s string) (*UDPAddr, error) { - host, port, err := net.SplitHostPort(s) + a, p, err := addr.ParseAddrPort(s) if err != nil { - return nil, serrors.WrapStr("invalid address: split host:port", err, "addr", s) - } - parts := strings.Split(host, ",") - if len(parts) != 2 { - return nil, serrors.New("invalid address: host parts invalid", - "expected", 2, "actual", len(parts)) - } - ia, err := addr.ParseIA(parts[0]) - if err != nil { - return nil, serrors.WrapStr("invalid address: IA not parsable", err, "ia", ia) - } - ip, err := netip.ParseAddr(parts[1]) - if err != nil { - return nil, serrors.WrapStr("invalid address: ip not parsable", err, "ip", parts[1]) - } - p, err := strconv.Atoi(port) - if err != nil { - return nil, serrors.WrapStr("invalid address: port invalid", err, "port", port) + return nil, err } udp := &net.UDPAddr{ - IP: ip.AsSlice(), - Zone: ip.Zone(), - Port: p, + IP: a.Host.IP().AsSlice(), + Zone: a.Host.IP().Zone(), + Port: int(p), } - return &UDPAddr{IA: ia, Host: udp}, nil + return &UDPAddr{IA: a.IA, Host: udp}, nil } // The legacy format of the SCION address URI encoding allows multiple different encodings. diff --git a/pkg/snet/writer.go b/pkg/snet/writer.go index f185542e2..70609f102 100644 --- a/pkg/snet/writer.go +++ b/pkg/snet/writer.go @@ -18,6 +18,7 @@ package snet import ( "fmt" "net" + "net/netip" "sync" "time" @@ -47,7 +48,11 @@ func (c *scionConnWriter) WriteTo(b []byte, raddr net.Addr) (int, error) { case nil: return 0, serrors.New("Missing remote address") case *UDPAddr: - dst = SCIONAddress{IA: a.IA, Host: addr.HostFromIP(a.Host.IP)} + hostIP, ok := netip.AddrFromSlice(a.Host.IP) + if !ok { + return 0, serrors.New("invalid destination host IP", "ip", a.Host.IP) + } + dst = SCIONAddress{IA: a.IA, Host: addr.HostIP(hostIP)} port, path = a.Host.Port, a.Path nextHop = a.NextHop if nextHop == nil && c.base.scionNet.LocalIA.Equal(a.IA) { @@ -59,20 +64,25 @@ func (c *scionConnWriter) WriteTo(b []byte, raddr net.Addr) (int, error) { } case *SVCAddr: - dst, port, path = SCIONAddress{IA: a.IA, Host: a.SVC}, 0, a.Path + dst, port, path = SCIONAddress{IA: a.IA, Host: addr.HostSVC(a.SVC)}, 0, a.Path nextHop = a.NextHop default: return 0, serrors.New("Unable to write to non-SCION address", "addr", fmt.Sprintf("%v(%T)", a, a)) } + listenHostIP, ok := netip.AddrFromSlice(c.base.listen.Host.IP) + if !ok { + return 0, serrors.New("invalid listen host IP", "ip", c.base.listen.Host.IP) + } + pkt := &Packet{ Bytes: Bytes(c.buffer), PacketInfo: PacketInfo{ Destination: dst, Source: SCIONAddress{ IA: c.base.scionNet.LocalIA, - Host: addr.HostFromIP(c.base.listen.Host.IP), + Host: addr.HostIP(listenHostIP), }, Path: path, Payload: UDPPayload{ diff --git a/pkg/sock/reliable/frame.go b/pkg/sock/reliable/frame.go index f0b64f865..31b8b938a 100644 --- a/pkg/sock/reliable/frame.go +++ b/pkg/sock/reliable/frame.go @@ -18,7 +18,6 @@ import ( "encoding/binary" "net" - "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/serrors" ) @@ -88,7 +87,7 @@ func (f *frame) DecodeFromBytes(data []byte) error { f.AddressType = data[8] f.Length = binary.BigEndian.Uint32(data[9:]) offset := 13 - addressType := addr.HostAddrType(f.AddressType) + addressType := hostAddrType(f.AddressType) if !isValidReliableSockDestination(addressType) { return serrors.WithCtx(ErrBadAddressType, "type", addressType) } @@ -136,8 +135,8 @@ func (f *frame) insertAddress(address *net.UDPAddr) error { } func (f *frame) extractAddress() *net.UDPAddr { - t := addr.HostAddrType(f.AddressType) - if t == addr.HostTypeIPv4 || t == addr.HostTypeIPv6 { + t := hostAddrType(f.AddressType) + if t == hostTypeIPv4 || t == hostTypeIPv6 { return &net.UDPAddr{ IP: net.IP(f.Address), Port: int(binary.BigEndian.Uint16(f.Port)), diff --git a/pkg/sock/reliable/mock_reliable/mock.go b/pkg/sock/reliable/mock_reliable/mock.go index 20893aa72..6dd921585 100644 --- a/pkg/sock/reliable/mock_reliable/mock.go +++ b/pkg/sock/reliable/mock_reliable/mock.go @@ -37,7 +37,7 @@ func (m *MockDispatcher) EXPECT() *MockDispatcherMockRecorder { } // Register mocks base method. -func (m *MockDispatcher) Register(arg0 context.Context, arg1 addr.IA, arg2 *net.UDPAddr, arg3 addr.HostSVC) (net.PacketConn, uint16, error) { +func (m *MockDispatcher) Register(arg0 context.Context, arg1 addr.IA, arg2 *net.UDPAddr, arg3 addr.SVC) (net.PacketConn, uint16, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Register", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(net.PacketConn) diff --git a/pkg/sock/reliable/packetizer.go b/pkg/sock/reliable/packetizer.go index 90e2c1c65..38485bf39 100644 --- a/pkg/sock/reliable/packetizer.go +++ b/pkg/sock/reliable/packetizer.go @@ -18,7 +18,6 @@ import ( "encoding/binary" "net" - "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/serrors" ) @@ -85,8 +84,8 @@ func (reader *ReadPacketizer) haveNextPacket(b []byte) []byte { } rcvdAddrType := b[8] payloadLength := binary.BigEndian.Uint32(b[9:13]) - addressLength := getAddressLength(addr.HostAddrType(rcvdAddrType)) - portLength := getPortLength(addr.HostAddrType(rcvdAddrType)) + addressLength := getAddressLength(hostAddrType(rcvdAddrType)) + portLength := getPortLength(hostAddrType(rcvdAddrType)) totalLength := 13 + addressLength + portLength + int(payloadLength) if len(b) < totalLength { return nil diff --git a/pkg/sock/reliable/reconnect/network.go b/pkg/sock/reliable/reconnect/network.go index 91f0df511..84358f283 100644 --- a/pkg/sock/reliable/reconnect/network.go +++ b/pkg/sock/reliable/reconnect/network.go @@ -45,7 +45,7 @@ func NewDispatcherService(dispatcher reliable.Dispatcher) *DispatcherService { } func (pn *DispatcherService) Register(ctx context.Context, ia addr.IA, public *net.UDPAddr, - svc addr.HostSVC) (net.PacketConn, uint16, error) { + svc addr.SVC) (net.PacketConn, uint16, error) { // Perform initial connection to allocate port. We use a reconnecter here // to set up the initial connection using the same retry logic we use when @@ -71,7 +71,7 @@ func (pn *DispatcherService) Register(ctx context.Context, ia addr.IA, public *n } func (pn *DispatcherService) newReconnecterFromListenArgs(ctx context.Context, ia addr.IA, - public *net.UDPAddr, svc addr.HostSVC) *TickingReconnecter { + public *net.UDPAddr, svc addr.SVC) *TickingReconnecter { // f represents individual connection attempts f := func(timeout time.Duration) (net.PacketConn, uint16, error) { diff --git a/pkg/sock/reliable/registration.go b/pkg/sock/reliable/registration.go index e7475825a..e4e7c87c9 100644 --- a/pkg/sock/reliable/registration.go +++ b/pkg/sock/reliable/registration.go @@ -35,7 +35,7 @@ type Registration struct { IA addr.IA PublicAddress *net.UDPAddr BindAddress *net.UDPAddr - SVCAddress addr.HostSVC + SVCAddress addr.SVC } func (r *Registration) SerializeTo(b []byte) (int, error) { @@ -78,7 +78,7 @@ func (r *Registration) DecodeFromBytes(b []byte) error { if len(msg.SVC) == 0 { r.SVCAddress = addr.SvcNone } else { - r.SVCAddress = addr.HostSVC(binary.BigEndian.Uint16(msg.SVC)) + r.SVCAddress = addr.SVC(binary.BigEndian.Uint16(msg.SVC)) } if (msg.Command & CmdBindAddress) != 0 { r.BindAddress = &net.UDPAddr{ @@ -175,10 +175,10 @@ func (l *registrationAddressField) DecodeFromBytes(b []byte) error { } l.Port = binary.BigEndian.Uint16(b[:2]) l.AddressType = b[2] - if !isValidReliableSockDestination(addr.HostAddrType(l.AddressType)) { + if !isValidReliableSockDestination(hostAddrType(l.AddressType)) { return ErrBadAddressType } - addressLength := getAddressLength(addr.HostAddrType(l.AddressType)) + addressLength := getAddressLength(hostAddrType(l.AddressType)) if len(b[3:]) < addressLength { return ErrIncompleteAddress } diff --git a/pkg/sock/reliable/reliable.go b/pkg/sock/reliable/reliable.go index c70afac0b..b3b3ed148 100644 --- a/pkg/sock/reliable/reliable.go +++ b/pkg/sock/reliable/reliable.go @@ -95,7 +95,7 @@ type Dispatcher interface { // Register connects to a SCION Dispatcher's UNIX socket. Future messages for the address in AS // ia which arrive at the dispatcher can be read by calling Read on the returned connection. Register(ctx context.Context, ia addr.IA, address *net.UDPAddr, - svc addr.HostSVC) (net.PacketConn, uint16, error) + svc addr.SVC) (net.PacketConn, uint16, error) } // NewDispatcher creates a new dispatcher API endpoint on top of a UNIX @@ -113,7 +113,7 @@ type dispatcherService struct { } func (d *dispatcherService) Register(ctx context.Context, ia addr.IA, public *net.UDPAddr, - svc addr.HostSVC) (net.PacketConn, uint16, error) { + svc addr.SVC) (net.PacketConn, uint16, error) { return registerMetricsWrapper(ctx, d.Address, ia, public, svc) } @@ -161,7 +161,7 @@ func Dial(ctx context.Context, address string) (*Conn, error) { } func registerMetricsWrapper(ctx context.Context, dispatcher string, ia addr.IA, - public *net.UDPAddr, svc addr.HostSVC) (*Conn, uint16, error) { + public *net.UDPAddr, svc addr.SVC) (*Conn, uint16, error) { conn, port, err := register(ctx, dispatcher, ia, public, svc) labels := metrics.RegisterLabels{Result: labelResult(err), SVC: svc.BaseString()} @@ -170,7 +170,7 @@ func registerMetricsWrapper(ctx context.Context, dispatcher string, ia addr.IA, } func register(ctx context.Context, dispatcher string, ia addr.IA, public *net.UDPAddr, - svc addr.HostSVC) (*Conn, uint16, error) { + svc addr.SVC) (*Conn, uint16, error) { reg := &Registration{ IA: ia, diff --git a/pkg/sock/reliable/util.go b/pkg/sock/reliable/util.go index f79dc256c..f0e49b0f5 100644 --- a/pkg/sock/reliable/util.go +++ b/pkg/sock/reliable/util.go @@ -16,22 +16,29 @@ package reliable import ( "net" +) + +type hostAddrType uint8 - "github.com/scionproto/scion/pkg/addr" +const ( + hostTypeNone = iota + hostTypeIPv4 + hostTypeIPv6 + hostTypeSVC ) -func getAddressType(address *net.UDPAddr) addr.HostAddrType { +func getAddressType(address *net.UDPAddr) hostAddrType { if address == nil || address.IP == nil { - return addr.HostTypeNone + return hostTypeNone } return getIPAddressType(address.IP) } -func getIPAddressType(ip net.IP) addr.HostAddrType { +func getIPAddressType(ip net.IP) hostAddrType { if ip.To4() != nil { - return addr.HostTypeIPv4 + return hostTypeIPv4 } - return addr.HostTypeIPv6 + return hostTypeIPv6 } // normalizeIP returns a 4-byte slice for an IPv4 address, and 16-byte slice @@ -43,17 +50,26 @@ func normalizeIP(ip net.IP) net.IP { return ip } -func isValidReliableSockDestination(t addr.HostAddrType) bool { - return t == addr.HostTypeNone || t == addr.HostTypeIPv4 || t == addr.HostTypeIPv6 +func isValidReliableSockDestination(t hostAddrType) bool { + return t == hostTypeNone || t == hostTypeIPv4 || t == hostTypeIPv6 } -func getAddressLength(t addr.HostAddrType) int { - n, _ := addr.HostLen(t) - return int(n) +func getAddressLength(t hostAddrType) int { + switch t { + case hostTypeNone: + return 0 + case hostTypeIPv4: + return 4 + case hostTypeIPv6: + return 16 + case hostTypeSVC: + return 2 + } + return 0 } -func getPortLength(t addr.HostAddrType) int { - if t == addr.HostTypeIPv4 || t == addr.HostTypeIPv6 { +func getPortLength(t hostAddrType) int { + if t == hostTypeIPv4 || t == hostTypeIPv6 { return 2 } return 0 diff --git a/pkg/spao/BUILD.bazel b/pkg/spao/BUILD.bazel index f047fd0e4..390c3f26c 100644 --- a/pkg/spao/BUILD.bazel +++ b/pkg/spao/BUILD.bazel @@ -30,7 +30,6 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/addr:go_default_library", "//pkg/drkey:go_default_library", "//pkg/private/xtest:go_default_library", "//pkg/slayers:go_default_library", diff --git a/pkg/spao/mac_test.go b/pkg/spao/mac_test.go index d9ad62fc2..08e6e8c16 100644 --- a/pkg/spao/mac_test.go +++ b/pkg/spao/mac_test.go @@ -24,7 +24,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -159,7 +158,7 @@ func TestComputeAuthMac(t *testing.T) { SrcAddrType: slayers.T16Ip, RawSrcAddr: net.ParseIP("2001:cafe::1").To16(), DstAddrType: slayers.T4Svc, - RawDstAddr: addr.HostSVCFromString("CS").Pack(), + RawDstAddr: nil, Path: decodedPath, PathType: decodedPath.Type(), }, diff --git a/private/app/appnet/addr.go b/private/app/appnet/addr.go index 19387e2f5..4bbd73303 100644 --- a/private/app/appnet/addr.go +++ b/private/app/appnet/addr.go @@ -33,7 +33,7 @@ import ( // SVC address to a unicast IP/UDP one. type Resolver interface { // LookupSVC resolves the SVC address for the AS terminating the path. - LookupSVC(ctx context.Context, path snet.Path, svc addr.HostSVC) (*svc.Reply, error) + LookupSVC(ctx context.Context, path snet.Path, svc addr.SVC) (*svc.Reply, error) } // AddressRewriter is used to compute paths and replace SVC destinations with @@ -174,7 +174,7 @@ func (r AddressRewriter) buildFullAddress(ctx context.Context, // The returned path is the path contained in the reply; the path can be used // to talk to the remote AS after One-Hop Path construction. func (r AddressRewriter) resolveSVC(ctx context.Context, p snet.Path, - s addr.HostSVC) (snet.Path, *net.UDPAddr, bool, error) { + s addr.SVC) (snet.Path, *net.UDPAddr, bool, error) { logger := log.FromCtx(ctx) if r.SVCResolutionFraction < 1.0 { var cancelF context.CancelFunc @@ -232,5 +232,5 @@ type SVCResolver interface { // GetUnderlay returns the underlay address of a SVC server of the specified // type. When multiple servers are available, the choice is random. If no // servers are available an error should be returned. - GetUnderlay(svc addr.HostSVC) (*net.UDPAddr, error) + GetUnderlay(svc addr.SVC) (*net.UDPAddr, error) } diff --git a/private/app/appnet/addr_test.go b/private/app/appnet/addr_test.go index 89b0e527d..27bba692c 100644 --- a/private/app/appnet/addr_test.go +++ b/private/app/appnet/addr_test.go @@ -318,7 +318,7 @@ func TestBuildFullAddress(t *testing.T) { func TestResolve(t *testing.T) { testCases := map[string]struct { - input addr.HostSVC + input addr.SVC ResolverSetup func(*mock_infraenv.MockResolver) SVCResolutionFraction float64 wantPath snet.Path diff --git a/private/app/appnet/export_test.go b/private/app/appnet/export_test.go index a6c3c57ca..47e689ebf 100644 --- a/private/app/appnet/export_test.go +++ b/private/app/appnet/export_test.go @@ -29,7 +29,7 @@ func (r AddressRewriter) BuildFullAddress(ctx context.Context, } func (r AddressRewriter) ResolveSVC(ctx context.Context, p snet.Path, - s addr.HostSVC) (snet.Path, *net.UDPAddr, bool, error) { + s addr.SVC) (snet.Path, *net.UDPAddr, bool, error) { return r.resolveSVC(ctx, p, s) } diff --git a/private/app/appnet/mock_infraenv/mock.go b/private/app/appnet/mock_infraenv/mock.go index 1a35fd832..920dda8a8 100644 --- a/private/app/appnet/mock_infraenv/mock.go +++ b/private/app/appnet/mock_infraenv/mock.go @@ -39,7 +39,7 @@ func (m *MockSVCResolver) EXPECT() *MockSVCResolverMockRecorder { } // GetUnderlay mocks base method. -func (m *MockSVCResolver) GetUnderlay(arg0 addr.HostSVC) (*net.UDPAddr, error) { +func (m *MockSVCResolver) GetUnderlay(arg0 addr.SVC) (*net.UDPAddr, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetUnderlay", arg0) ret0, _ := ret[0].(*net.UDPAddr) @@ -77,7 +77,7 @@ func (m *MockResolver) EXPECT() *MockResolverMockRecorder { } // LookupSVC mocks base method. -func (m *MockResolver) LookupSVC(arg0 context.Context, arg1 snet.Path, arg2 addr.HostSVC) (*svc.Reply, error) { +func (m *MockResolver) LookupSVC(arg0 context.Context, arg1 snet.Path, arg2 addr.SVC) (*svc.Reply, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LookupSVC", arg0, arg1, arg2) ret0, _ := ret[0].(*svc.Reply) diff --git a/private/app/path/pathprobe/paths.go b/private/app/path/pathprobe/paths.go index 5a64f601c..951d27d59 100644 --- a/private/app/path/pathprobe/paths.go +++ b/private/app/path/pathprobe/paths.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "net" + "net/netip" "os" "sync" "sync/atomic" @@ -55,7 +56,7 @@ const ( // Status indicates the state a path is in. type Status struct { Status StatusName - LocalIP net.IP + LocalIP netip.Addr AdditionalInfo string } @@ -172,10 +173,11 @@ func (p Prober) GetStatuses(ctx context.Context, paths []snet.Path, // Resolve all the local IPs per path. We will open one connection // per local IP address. - pathsPerIP := map[string][]snet.Path{} + pathsPerIP := map[netip.Addr][]snet.Path{} for _, path := range paths { - localIP, err := p.resolveLocalIP(path.UnderlayNextHop()) - if err != nil { + localIPSlice, err := p.resolveLocalIP(path.UnderlayNextHop()) + localIP, ok := netip.AddrFromSlice(localIPSlice) + if err != nil || !ok { addStatus( PathKey(path), Status{ @@ -185,20 +187,20 @@ func (p Prober) GetStatuses(ctx context.Context, paths []snet.Path, ) continue } - pathsPerIP[localIP.String()] = append(pathsPerIP[localIP.String()], path) + pathsPerIP[localIP] = append(pathsPerIP[localIP], path) addStatus(PathKey(path), Status{Status: StatusTimeout, LocalIP: localIP}) } // Sequence number for the sent traceroute packets. var seq int32 g, _ := errgroup.WithContext(ctx) - for ip, paths := range pathsPerIP { - ip, paths := ip, paths + for localIP, paths := range pathsPerIP { + localIP, paths := localIP, paths g.Go(func() error { defer log.HandlePanic() - localIP := net.ParseIP(ip) - conn, _, err := disp.Register(ctx, p.LocalIA, &net.UDPAddr{IP: localIP}, addr.SvcNone) + conn, _, err := disp.Register(ctx, p.LocalIA, + &net.UDPAddr{IP: localIP.AsSlice()}, addr.SvcNone) if err != nil { return serrors.WrapStr("creating packet conn", err, "local", localIP) } @@ -236,11 +238,11 @@ func (p Prober) GetStatuses(ctx context.Context, paths []snet.Path, PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: p.DstIA, - Host: addr.SvcNone, + Host: addr.HostSVC(addr.SvcNone), }, Source: snet.SCIONAddress{ IA: p.LocalIA, - Host: addr.HostFromIP(localIP), + Host: addr.HostIP(localIP), }, Path: alertPath, Payload: snet.SCMPTracerouteRequest{ diff --git a/private/svc/resolver.go b/private/svc/resolver.go index ad0c2190c..fb01fb173 100644 --- a/private/svc/resolver.go +++ b/private/svc/resolver.go @@ -17,6 +17,7 @@ package svc import ( "context" "net" + "net/netip" "github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go/ext" @@ -68,7 +69,7 @@ type Resolver struct { } // LookupSVC resolves the SVC address for the AS terminating the path. -func (r *Resolver) LookupSVC(ctx context.Context, p snet.Path, svc addr.HostSVC) (*Reply, error) { +func (r *Resolver) LookupSVC(ctx context.Context, p snet.Path, svc addr.SVC) (*Reply, error) { var span opentracing.Span span, ctx = opentracing.StartSpanFromContext(ctx, "svc.resolution") span.SetTag("svc", svc.String()) @@ -78,6 +79,10 @@ func (r *Resolver) LookupSVC(ctx context.Context, p snet.Path, svc addr.HostSVC) u := &net.UDPAddr{ IP: r.LocalIP, } + localIP, ok := netip.AddrFromSlice(r.LocalIP) + if !ok { + return nil, serrors.New("invalid local IP", "ip", r.LocalIP) + } conn, port, err := r.ConnFactory.Register(ctx, r.LocalIA, u, addr.SvcNone) if err != nil { @@ -95,11 +100,11 @@ func (r *Resolver) LookupSVC(ctx context.Context, p snet.Path, svc addr.HostSVC) PacketInfo: snet.PacketInfo{ Source: snet.SCIONAddress{ IA: r.LocalIA, - Host: addr.HostFromIP(r.LocalIP), + Host: addr.HostIP(localIP), }, Destination: snet.SCIONAddress{ IA: p.Destination(), - Host: svc, + Host: addr.HostSVC(svc), }, Path: p.Dataplane(), Payload: snet.UDPPayload{ diff --git a/private/svc/resolver_test.go b/private/svc/resolver_test.go index 72325863e..86a47bf57 100644 --- a/private/svc/resolver_test.go +++ b/private/svc/resolver_test.go @@ -55,6 +55,7 @@ func TestResolver(t *testing.T) { resolver := &svc.Resolver{ LocalIA: srcIA, ConnFactory: mockPacketDispatcherService, + LocalIP: net.IP{0, 0, 0, 0}, } reply, err := resolver.LookupSVC(context.Background(), mockPath, addr.SvcCS) diff --git a/private/svc/svc.go b/private/svc/svc.go index c9e0666f8..e7451f25c 100644 --- a/private/svc/svc.go +++ b/private/svc/svc.go @@ -18,6 +18,7 @@ package svc import ( "context" "net" + "net/netip" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/common" @@ -72,8 +73,12 @@ type ResolverPacketDispatcher struct { } func (d *ResolverPacketDispatcher) Register(ctx context.Context, ia addr.IA, - registration *net.UDPAddr, svc addr.HostSVC) (snet.PacketConn, uint16, error) { + registration *net.UDPAddr, svc addr.SVC) (snet.PacketConn, uint16, error) { + registrationIP, ok := netip.AddrFromSlice(registration.IP) + if !ok { + return nil, 0, serrors.New("invalid registration IP", "ip", registration.IP) + } c, port, err := d.dispService.Register(ctx, ia, registration, svc) if err != nil { return nil, 0, err @@ -82,7 +87,7 @@ func (d *ResolverPacketDispatcher) Register(ctx context.Context, ia addr.IA, PacketConn: c, source: snet.SCIONAddress{ IA: ia, - Host: addr.HostFromIP(registration.IP), + Host: addr.HostIP(registrationIP), }, handler: d.handler, } @@ -107,11 +112,11 @@ func (c *resolverPacketConn) ReadFrom(pkt *snet.Packet, ov *net.UDPAddr) error { } // XXX(scrye): destination address is guaranteed to not be nil - svc, ok := pkt.Destination.Host.(addr.HostSVC) - if !ok { + if pkt.Destination.Host.Type() != addr.HostTypeSVC { // Normal packet, return to caller because data is already parsed and ready return nil } + svc := pkt.Destination.Host.SVC() // Multicasts do not trigger SVC resolution logic if svc.IsMulticast() { diff --git a/private/svc/svc_test.go b/private/svc/svc_test.go index 2abade4a4..f6aed7233 100644 --- a/private/svc/svc_test.go +++ b/private/svc/svc_test.go @@ -59,7 +59,7 @@ func TestSVCResolutionServer(t *testing.T) { mockPacketConn.EXPECT().ReadFrom(gomock.Any(), gomock.Any()).DoAndReturn( func(pkt *snet.Packet, ov *net.UDPAddr) error { pkt.Destination = snet.SCIONAddress{ - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), } return nil }, @@ -85,7 +85,7 @@ func TestSVCResolutionServer(t *testing.T) { mockPacketConn.EXPECT().ReadFrom(gomock.Any(), gomock.Any()).DoAndReturn( func(pkt *snet.Packet, ov *net.UDPAddr) error { pkt.Destination = snet.SCIONAddress{ - Host: addr.SvcCS, + Host: addr.HostSVC(addr.SvcCS), } return nil }, @@ -111,7 +111,7 @@ func TestSVCResolutionServer(t *testing.T) { mockPacketConn.EXPECT().ReadFrom(gomock.Any(), gomock.Any()).DoAndReturn( func(pkt *snet.Packet, ov *net.UDPAddr) error { pkt.Destination = snet.SCIONAddress{ - Host: addr.HostIPv4(net.IP{192, 168, 0, 1}), + Host: addr.MustParseHost("192.168.0.1"), } return nil }, @@ -160,7 +160,7 @@ func TestSVCResolutionServer(t *testing.T) { mockPacketConn.EXPECT().ReadFrom(gomock.Any(), gomock.Any()).DoAndReturn( func(pkt *snet.Packet, ov *net.UDPAddr) error { pkt.Destination = snet.SCIONAddress{ - Host: addr.SvcCS.Multicast(), + Host: addr.HostSVC(addr.SvcCS.Multicast()), } return nil }, @@ -190,7 +190,8 @@ func TestSVCResolutionServer(t *testing.T) { defer ctrl.Finish() disp := svc.NewResolverPacketDispatcher(tc.DispService(ctrl), tc.ReqHandler(ctrl)) - conn, port, err := disp.Register(context.Background(), 0, &net.UDPAddr{}, + conn, port, err := disp.Register(context.Background(), 0, + &net.UDPAddr{IP: net.ParseIP("198.51.100.1")}, addr.SvcCS) tc.ErrRegister(t, err) @@ -280,7 +281,7 @@ func TestDefaultHandler(t *testing.T) { }, }, "Source address override": { - ReplySource: snet.SCIONAddress{Host: addr.HostIPv4(net.IP{192, 168, 0, 1})}, + ReplySource: snet.SCIONAddress{Host: addr.MustParseHost("192.168.0.1")}, InputPacket: &snet.Packet{ PacketInfo: snet.PacketInfo{ Payload: snet.UDPPayload{}, @@ -289,7 +290,7 @@ func TestDefaultHandler(t *testing.T) { }, ExpectedPacket: &snet.Packet{ PacketInfo: snet.PacketInfo{ - Source: snet.SCIONAddress{Host: addr.HostIPv4(net.IP{192, 168, 0, 1})}, + Source: snet.SCIONAddress{Host: addr.MustParseHost("192.168.0.1")}, Payload: snet.UDPPayload{}, Path: snet.RawReplyPath{ Path: empty.Path{}, diff --git a/private/topology/interface.go b/private/topology/interface.go index 868414d23..f6440c177 100644 --- a/private/topology/interface.go +++ b/private/topology/interface.go @@ -43,17 +43,17 @@ type Topology interface { // PublicAddress gets the public address of a server with the requested type and name, and nil // if no such server exists. - PublicAddress(svc addr.HostSVC, name string) *net.UDPAddr + PublicAddress(svc addr.SVC, name string) *net.UDPAddr // Anycast returns the address for an arbitrary server of the requested type. - Anycast(svc addr.HostSVC) (*net.UDPAddr, error) + Anycast(svc addr.SVC) (*net.UDPAddr, error) // Multicast returns all addresses for the requested type. - Multicast(svc addr.HostSVC) ([]*net.UDPAddr, error) + Multicast(svc addr.SVC) ([]*net.UDPAddr, error) // UnderlayAnycast returns the underlay address for an arbitrary server of the requested type. - UnderlayAnycast(svc addr.HostSVC) (*net.UDPAddr, error) + UnderlayAnycast(svc addr.SVC) (*net.UDPAddr, error) // UnderlayMulticast returns all underlay addresses for the requested type. - UnderlayMulticast(svc addr.HostSVC) ([]*net.UDPAddr, error) + UnderlayMulticast(svc addr.SVC) ([]*net.UDPAddr, error) // UnderlayNextHop returns the internal underlay address of the router // containing the interface ID. UnderlayNextHop(ifID common.IFIDType) (*net.UDPAddr, bool) @@ -89,7 +89,7 @@ type Topology interface { // FIXME(scrye): Remove this, callers shouldn't care about names. // // XXX(scrye): Return value is a shallow copy. - SVCNames(svc addr.HostSVC) ServiceNames + SVCNames(svc addr.SVC) ServiceNames // Writable returns a pointer to the underlying topology object. This is included for legacy // reasons and should never be used. @@ -203,7 +203,7 @@ func (t *topologyS) BR(name string) (BRInfo, bool) { return br, ok } -func (t *topologyS) PublicAddress(svc addr.HostSVC, name string) *net.UDPAddr { +func (t *topologyS) PublicAddress(svc addr.SVC, name string) *net.UDPAddr { topoAddr := t.topoAddress(svc, name) if topoAddr == nil { return nil @@ -211,7 +211,7 @@ func (t *topologyS) PublicAddress(svc addr.HostSVC, name string) *net.UDPAddr { return topoAddr.SCIONAddress } -func (t *topologyS) topoAddress(svc addr.HostSVC, name string) *TopoAddr { +func (t *topologyS) topoAddress(svc addr.SVC, name string) *TopoAddr { var addresses IDAddrMap switch svc.Base() { case addr.SvcDS: @@ -225,7 +225,7 @@ func (t *topologyS) topoAddress(svc addr.HostSVC, name string) *TopoAddr { return addresses.GetByID(name) } -func (t *topologyS) Anycast(svc addr.HostSVC) (*net.UDPAddr, error) { +func (t *topologyS) Anycast(svc addr.SVC) (*net.UDPAddr, error) { addrs, err := t.Multicast(svc) if err != nil { return nil, err @@ -233,7 +233,7 @@ func (t *topologyS) Anycast(svc addr.HostSVC) (*net.UDPAddr, error) { return addrs[rand.Intn(len(addrs))], nil } -func (t *topologyS) Multicast(svc addr.HostSVC) ([]*net.UDPAddr, error) { +func (t *topologyS) Multicast(svc addr.SVC) ([]*net.UDPAddr, error) { st, err := toServiceType(svc) if err != nil { return nil, err @@ -257,7 +257,7 @@ func (t *topologyS) Multicast(svc addr.HostSVC) ([]*net.UDPAddr, error) { return addrs, nil } -func (t *topologyS) UnderlayAnycast(svc addr.HostSVC) (*net.UDPAddr, error) { +func (t *topologyS) UnderlayAnycast(svc addr.SVC) (*net.UDPAddr, error) { names := t.SVCNames(svc) name, err := names.GetRandom() if err != nil { @@ -275,12 +275,12 @@ func (t *topologyS) UnderlayAnycast(svc addr.HostSVC) (*net.UDPAddr, error) { return underlay, nil } -func supportedSVC(svc addr.HostSVC) bool { +func supportedSVC(svc addr.SVC) bool { b := svc.Base() return b == addr.SvcDS || b == addr.SvcCS } -func (t *topologyS) UnderlayMulticast(svc addr.HostSVC) ([]*net.UDPAddr, error) { +func (t *topologyS) UnderlayMulticast(svc addr.SVC) ([]*net.UDPAddr, error) { st, err := toServiceType(svc) if err != nil { return nil, err @@ -312,7 +312,7 @@ func (t *topologyS) UnderlayMulticast(svc addr.HostSVC) ([]*net.UDPAddr, error) return underlayAddrs, nil } -func (t *topologyS) underlayByName(svc addr.HostSVC, name string) (*net.UDPAddr, error) { +func (t *topologyS) underlayByName(svc addr.SVC, name string) (*net.UDPAddr, error) { st, err := toServiceType(svc) if err != nil { return nil, err @@ -328,7 +328,7 @@ func (t *topologyS) underlayByName(svc addr.HostSVC, name string) (*net.UDPAddr, return copyUDPAddr(underlayAddr), nil } -func toServiceType(svc addr.HostSVC) (ServiceType, error) { +func toServiceType(svc addr.SVC) (ServiceType, error) { switch svc.Base() { case addr.SvcDS: return Discovery, nil @@ -347,7 +347,7 @@ func (t *topologyS) BRNames() []string { return t.Topology.BRNames } -func (t *topologyS) SVCNames(svc addr.HostSVC) ServiceNames { +func (t *topologyS) SVCNames(svc addr.SVC) ServiceNames { var m IDAddrMap switch svc.Base() { case addr.SvcDS: diff --git a/private/topology/mock_topology/mock.go b/private/topology/mock_topology/mock.go index 62832c8b4..2c33bb48b 100644 --- a/private/topology/mock_topology/mock.go +++ b/private/topology/mock_topology/mock.go @@ -38,7 +38,7 @@ func (m *MockTopology) EXPECT() *MockTopologyMockRecorder { } // Anycast mocks base method. -func (m *MockTopology) Anycast(arg0 addr.HostSVC) (*net.UDPAddr, error) { +func (m *MockTopology) Anycast(arg0 addr.SVC) (*net.UDPAddr, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Anycast", arg0) ret0, _ := ret[0].(*net.UDPAddr) @@ -182,7 +182,7 @@ func (mr *MockTopologyMockRecorder) MakeHostInfos(arg0 interface{}) *gomock.Call } // Multicast mocks base method. -func (m *MockTopology) Multicast(arg0 addr.HostSVC) ([]*net.UDPAddr, error) { +func (m *MockTopology) Multicast(arg0 addr.SVC) ([]*net.UDPAddr, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Multicast", arg0) ret0, _ := ret[0].([]*net.UDPAddr) @@ -197,7 +197,7 @@ func (mr *MockTopologyMockRecorder) Multicast(arg0 interface{}) *gomock.Call { } // PublicAddress mocks base method. -func (m *MockTopology) PublicAddress(arg0 addr.HostSVC, arg1 string) *net.UDPAddr { +func (m *MockTopology) PublicAddress(arg0 addr.SVC, arg1 string) *net.UDPAddr { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PublicAddress", arg0, arg1) ret0, _ := ret[0].(*net.UDPAddr) @@ -211,7 +211,7 @@ func (mr *MockTopologyMockRecorder) PublicAddress(arg0, arg1 interface{}) *gomoc } // SVCNames mocks base method. -func (m *MockTopology) SVCNames(arg0 addr.HostSVC) topology.ServiceNames { +func (m *MockTopology) SVCNames(arg0 addr.SVC) topology.ServiceNames { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SVCNames", arg0) ret0, _ := ret[0].(topology.ServiceNames) @@ -225,7 +225,7 @@ func (mr *MockTopologyMockRecorder) SVCNames(arg0 interface{}) *gomock.Call { } // UnderlayAnycast mocks base method. -func (m *MockTopology) UnderlayAnycast(arg0 addr.HostSVC) (*net.UDPAddr, error) { +func (m *MockTopology) UnderlayAnycast(arg0 addr.SVC) (*net.UDPAddr, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "UnderlayAnycast", arg0) ret0, _ := ret[0].(*net.UDPAddr) @@ -240,7 +240,7 @@ func (mr *MockTopologyMockRecorder) UnderlayAnycast(arg0 interface{}) *gomock.Ca } // UnderlayMulticast mocks base method. -func (m *MockTopology) UnderlayMulticast(arg0 addr.HostSVC) ([]*net.UDPAddr, error) { +func (m *MockTopology) UnderlayMulticast(arg0 addr.SVC) ([]*net.UDPAddr, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "UnderlayMulticast", arg0) ret0, _ := ret[0].([]*net.UDPAddr) diff --git a/private/topology/reload.go b/private/topology/reload.go index 196174b18..74f974681 100644 --- a/private/topology/reload.go +++ b/private/topology/reload.go @@ -207,7 +207,7 @@ func (l *Loader) HiddenSegmentRegistrationAddresses() ([]*net.UDPAddr, error) { } // TODO(lukedirtwalker): remove error / cleanup. -func (l *Loader) GetUnderlay(svc addr.HostSVC) (*net.UDPAddr, error) { +func (l *Loader) GetUnderlay(svc addr.SVC) (*net.UDPAddr, error) { l.mtx.Lock() defer l.mtx.Unlock() diff --git a/router/connector.go b/router/connector.go index f2bd76721..6944e75b2 100644 --- a/router/connector.go +++ b/router/connector.go @@ -145,7 +145,7 @@ func (c *Connector) AddExternalInterface(localIfID common.IFIDType, link control } // AddSvc adds the service address for the given ISD-AS. -func (c *Connector) AddSvc(ia addr.IA, svc addr.HostSVC, ip net.IP) error { +func (c *Connector) AddSvc(ia addr.IA, svc addr.SVC, ip net.IP) error { c.mtx.Lock() defer c.mtx.Unlock() log.Debug("Adding service", "isd_as", ia, "svc", svc, "ip", ip) @@ -156,7 +156,7 @@ func (c *Connector) AddSvc(ia addr.IA, svc addr.HostSVC, ip net.IP) error { } // DelSvc deletes the service entry for the given ISD-AS and IP pair. -func (c *Connector) DelSvc(ia addr.IA, svc addr.HostSVC, ip net.IP) error { +func (c *Connector) DelSvc(ia addr.IA, svc addr.SVC, ip net.IP) error { c.mtx.Lock() defer c.mtx.Unlock() log.Debug("Deleting service", "isd_as", ia, "svc", svc, "ip", ip) diff --git a/router/control/conf.go b/router/control/conf.go index b11e4c27d..1e68e892c 100644 --- a/router/control/conf.go +++ b/router/control/conf.go @@ -34,8 +34,8 @@ type Dataplane interface { CreateIACtx(ia addr.IA) error AddInternalInterface(ia addr.IA, local net.UDPAddr) error AddExternalInterface(localIfID common.IFIDType, info LinkInfo, owned bool) error - AddSvc(ia addr.IA, svc addr.HostSVC, ip net.IP) error - DelSvc(ia addr.IA, svc addr.HostSVC, ip net.IP) error + AddSvc(ia addr.IA, svc addr.SVC, ip net.IP) error + DelSvc(ia addr.IA, svc addr.SVC, ip net.IP) error SetKey(ia addr.IA, index int, key []byte) error } @@ -206,7 +206,7 @@ func confExternalInterfaces(dp Dataplane, cfg *Config) error { return nil } -var svcTypes = []addr.HostSVC{ +var svcTypes = []addr.SVC{ addr.SvcDS, addr.SvcCS, } diff --git a/router/dataplane.go b/router/dataplane.go index 341097968..81592f3cd 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -24,6 +24,7 @@ import ( "hash" "math/big" "net" + "net/netip" "strconv" "sync" "syscall" @@ -99,7 +100,7 @@ type DataPlane struct { linkTypes map[uint16]topology.LinkType neighborIAs map[uint16]addr.IA internal BatchConn - internalIP *net.IPAddr + internalIP netip.Addr internalNextHops map[uint16]*net.UDPAddr svc *services macFactory func() hash.Hash @@ -132,7 +133,7 @@ var ( ) type drkeyProvider interface { - GetAuthKey(validTime time.Time, dstIA addr.IA, dstAddr net.Addr) (drkey.Key, error) + GetAuthKey(validTime time.Time, dstIA addr.IA, dstAddr addr.Host) (drkey.Key, error) } type scmpError struct { @@ -203,7 +204,11 @@ func (d *DataPlane) AddInternalInterface(conn BatchConn, ip net.IP) error { return alreadySet } d.internal = conn - d.internalIP = &net.IPAddr{IP: ip} + var ok bool + d.internalIP, ok = netip.AddrFromSlice(ip) + if !ok { + return serrors.New("invalid ip", "ip", ip) + } return nil } @@ -291,7 +296,10 @@ func (d *DataPlane) AddExternalInterfaceBFD(ifID uint16, conn BatchConn, PacketsReceived: d.Metrics.BFDPacketsReceived.With(labels), } } - s := newBFDSend(conn, src.IA, dst.IA, src.Addr, dst.Addr, ifID, d.macFactory()) + s, err := newBFDSend(conn, src.IA, dst.IA, src.Addr, dst.Addr, ifID, d.macFactory()) + if err != nil { + return err + } return d.addBFDController(ifID, s, cfg, m) } @@ -337,7 +345,7 @@ func (d *DataPlane) addBFDController(ifID uint16, s *bfdSend, cfg control.BFD, // AddSvc adds the address for the given service. This can be called multiple // times for the same service, with the address added to the list of addresses // that provide the service. -func (d *DataPlane) AddSvc(svc addr.HostSVC, a *net.UDPAddr) error { +func (d *DataPlane) AddSvc(svc addr.SVC, a *net.UDPAddr) error { d.mtx.Lock() defer d.mtx.Unlock() if a == nil { @@ -356,7 +364,7 @@ func (d *DataPlane) AddSvc(svc addr.HostSVC, a *net.UDPAddr) error { } // DelSvc deletes the address for the given service. -func (d *DataPlane) DelSvc(svc addr.HostSVC, a *net.UDPAddr) error { +func (d *DataPlane) DelSvc(svc addr.SVC, a *net.UDPAddr) error { d.mtx.Lock() defer d.mtx.Unlock() if a == nil { @@ -431,7 +439,10 @@ func (d *DataPlane) AddNextHopBFD(ifID uint16, src, dst *net.UDPAddr, cfg contro } } - s := newBFDSend(d.internal, d.localIA, d.localIA, src, dst, 0, d.macFactory()) + s, err := newBFDSend(d.internal, d.localIA, d.localIA, src, dst, 0, d.macFactory()) + if err != nil { + return err + } return d.addBFDController(ifID, s, cfg, m) } @@ -1426,24 +1437,24 @@ func (d *DataPlane) resolveLocalDst(s slayers.SCION) (*net.UDPAddr, error) { // TODO parameter problem. return nil, err } - switch v := dst.(type) { - case addr.HostSVC: + switch dst.Type() { + case addr.HostTypeSVC: // For map lookup use the Base address, i.e. strip the multi cast // information, because we only register base addresses in the map. - a, ok := d.svc.Any(v.Base()) + a, ok := d.svc.Any(dst.SVC().Base()) if !ok { return nil, noSVCBackend } return a, nil - case *net.IPAddr: - return addEndhostPort(v), nil + case addr.HostTypeIP: + return addEndhostPort(dst.IP().AsSlice()), nil default: panic("unexpected address type returned from DstAddr") } } -func addEndhostPort(dst *net.IPAddr) *net.UDPAddr { - return &net.UDPAddr{IP: dst.IP, Port: topology.EndhostPort} +func addEndhostPort(dst net.IP) *net.UDPAddr { + return &net.UDPAddr{IP: dst, Port: topology.EndhostPort} } // TODO(matzf) this function is now only used to update the OneHop-path. @@ -1476,7 +1487,7 @@ type bfdSend struct { // newBFDSend creates and initializes a BFD Sender func newBFDSend(conn BatchConn, srcIA, dstIA addr.IA, srcAddr, dstAddr *net.UDPAddr, - ifID uint16, mac hash.Hash) *bfdSend { + ifID uint16, mac hash.Hash) (*bfdSend, error) { scn := &slayers.SCION{ Version: 0, @@ -1487,11 +1498,19 @@ func newBFDSend(conn BatchConn, srcIA, dstIA addr.IA, srcAddr, dstAddr *net.UDPA DstIA: dstIA, } - if err := scn.SetSrcAddr(&net.IPAddr{IP: srcAddr.IP}); err != nil { - panic(err) // Must work unless IPAddr is not supported + srcAddrIP, ok := netip.AddrFromSlice(srcAddr.IP) + if !ok { + return nil, serrors.New("invalid source IP", "ip", srcAddr.IP) } - if err := scn.SetDstAddr(&net.IPAddr{IP: dstAddr.IP}); err != nil { - panic(err) // Must work unless IPAddr is not supported + dstAddrIP, ok := netip.AddrFromSlice(dstAddr.IP) + if !ok { + return nil, serrors.New("invalid destination IP", "ip", dstAddr.IP) + } + if err := scn.SetSrcAddr(addr.HostIP(srcAddrIP)); err != nil { + panic(err) // Must work + } + if err := scn.SetDstAddr(addr.HostIP(dstAddrIP)); err != nil { + panic(err) // Must work } var ohp *onehop.Path @@ -1522,7 +1541,7 @@ func newBFDSend(conn BatchConn, srcIA, dstIA addr.IA, srcAddr, dstAddr *net.UDPA mac: mac, macBuffer: make([]byte, path.MACBufferSize), buffer: gopacket.NewSerializeBuffer(), - } + }, nil } func (b *bfdSend) String() string { @@ -1624,7 +1643,7 @@ func (p *scionPacketProcessor) prepareSCMP( if err := scionL.SetDstAddr(srcA); err != nil { return nil, serrors.Wrap(cannotRoute, err, "details", "setting dest addr") } - if err := scionL.SetSrcAddr(p.d.internalIP); err != nil { + if err := scionL.SetSrcAddr(addr.HostIP(p.d.internalIP)); err != nil { return nil, serrors.Wrap(cannotRoute, err, "details", "setting src addr") } scionL.NextHdr = slayers.L4SCMP @@ -1894,7 +1913,7 @@ func interfaceToMetricLabels(id uint16, localIA addr.IA, } } -func serviceMetricLabels(localIA addr.IA, svc addr.HostSVC) prometheus.Labels { +func serviceMetricLabels(localIA addr.IA, svc addr.SVC) prometheus.Labels { return prometheus.Labels{ "isd_as": localIA.String(), "service": svc.BaseString(), @@ -1906,7 +1925,7 @@ type fakeProvider struct{} func (p *fakeProvider) GetAuthKey( _ time.Time, _ addr.IA, - _ net.Addr, + _ addr.Host, ) (drkey.Key, error) { return drkey.Key{}, nil } diff --git a/router/dataplane_test.go b/router/dataplane_test.go index d68d95336..effd7199c 100644 --- a/router/dataplane_test.go +++ b/router/dataplane_test.go @@ -19,6 +19,7 @@ import ( "context" "fmt" "net" + "net/netip" "sync" "syscall" "testing" @@ -50,13 +51,14 @@ import ( ) func TestDataPlaneAddInternalInterface(t *testing.T) { + internalIP := net.ParseIP("198.51.100.1") t.Run("fails after serve", func(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() d := &router.DataPlane{} d.FakeStart() - assert.Error(t, d.AddInternalInterface(mock_router.NewMockBatchConn(ctrl), net.IP{})) + assert.Error(t, d.AddInternalInterface(mock_router.NewMockBatchConn(ctrl), internalIP)) }) t.Run("setting nil value is not allowed", func(t *testing.T) { ctrl := gomock.NewController(t) @@ -70,15 +72,15 @@ func TestDataPlaneAddInternalInterface(t *testing.T) { defer ctrl.Finish() d := &router.DataPlane{} - assert.NoError(t, d.AddInternalInterface(mock_router.NewMockBatchConn(ctrl), net.IP{})) + assert.NoError(t, d.AddInternalInterface(mock_router.NewMockBatchConn(ctrl), internalIP)) }) t.Run("double set fails", func(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() d := &router.DataPlane{} - assert.NoError(t, d.AddInternalInterface(mock_router.NewMockBatchConn(ctrl), net.IP{})) - assert.Error(t, d.AddInternalInterface(mock_router.NewMockBatchConn(ctrl), net.IP{})) + assert.NoError(t, d.AddInternalInterface(mock_router.NewMockBatchConn(ctrl), internalIP)) + assert.Error(t, d.AddInternalInterface(mock_router.NewMockBatchConn(ctrl), internalIP)) }) } @@ -278,7 +280,8 @@ func TestDataPlaneRun(t *testing.T) { YourDiscriminator: 0, } - _ = scn.SetSrcAddr(&net.IPAddr{IP: src.IP}) + srcIP, _ := netip.AddrFromSlice(src.IP) + _ = scn.SetSrcAddr(addr.HostIP(srcIP)) buffer := gopacket.NewSerializeBuffer() _ = gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{FixLengths: true}, scn, bfdL) @@ -363,7 +366,7 @@ func TestDataPlaneRun(t *testing.T) { if err != nil { return 1, nil } - if !bytes.Equal(a.(*net.IPAddr).IP, localAddr.IP) { + if !bytes.Equal(a.IP().AsSlice(), localAddr.IP) { return 1, nil } @@ -371,7 +374,7 @@ func TestDataPlaneRun(t *testing.T) { if err != nil { return 1, nil } - if !bytes.Equal(b.(*net.IPAddr).IP, remoteAddr.IP) { + if !bytes.Equal(b.IP().AsSlice(), remoteAddr.IP) { return 1, nil } @@ -581,7 +584,7 @@ func TestProcessPkt(t *testing.T) { mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, dpath := prepBaseMsg(now) spkt.DstIA = xtest.MustParseIA("1-ff00:0:110") - dst := &net.IPAddr{IP: net.ParseIP("10.0.100.100").To4()} + dst := addr.MustParseHost("10.0.100.100") _ = spkt.SetDstAddr(dst) dpath.HopFields = []path.HopField{ {ConsIngress: 41, ConsEgress: 40}, @@ -592,7 +595,7 @@ func TestProcessPkt(t *testing.T) { dpath.HopFields[2].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[2]) ret := toMsg(t, spkt, dpath) if afterProcessing { - ret.Addr = &net.UDPAddr{IP: dst.IP, Port: topology.EndhostPort} + ret.Addr = &net.UDPAddr{IP: dst.IP().AsSlice(), Port: topology.EndhostPort} ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil } return ret @@ -787,8 +790,8 @@ func TestProcessPkt(t *testing.T) { "svc": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - map[addr.HostSVC][]*net.UDPAddr{ - addr.HostSVCFromString("CS"): { + map[addr.SVC][]*net.UDPAddr{ + addr.SvcCS: { &net.UDPAddr{ IP: net.ParseIP("10.0.200.200").To4(), Port: topology.EndhostPort, @@ -799,7 +802,7 @@ func TestProcessPkt(t *testing.T) { }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, dpath := prepBaseMsg(now) - _ = spkt.SetDstAddr(addr.HostSVCFromString("CS")) + _ = spkt.SetDstAddr(addr.MustParseHost("CS")) spkt.DstIA = xtest.MustParseIA("1-ff00:0:110") dpath.HopFields = []path.HopField{ {ConsIngress: 41, ConsEgress: 40}, @@ -822,12 +825,12 @@ func TestProcessPkt(t *testing.T) { "svc nobackend": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - map[addr.HostSVC][]*net.UDPAddr{}, + map[addr.SVC][]*net.UDPAddr{}, xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, dpath := prepBaseMsg(now) - _ = spkt.SetDstAddr(addr.HostSVCFromString("CS")) + _ = spkt.SetDstAddr(addr.MustParseHost("CS")) spkt.DstIA = xtest.MustParseIA("1-ff00:0:110") dpath.HopFields = []path.HopField{ {ConsIngress: 41, ConsEgress: 40}, @@ -845,12 +848,12 @@ func TestProcessPkt(t *testing.T) { "svc invalid": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - map[addr.HostSVC][]*net.UDPAddr{}, + map[addr.SVC][]*net.UDPAddr{}, xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, dpath := prepBaseMsg(now) - _ = spkt.SetDstAddr(addr.HostSVCFromString("BS")) + _ = spkt.SetDstAddr(addr.MustParseHost("CS")) spkt.DstIA = xtest.MustParseIA("1-ff00:0:110") dpath.HopFields = []path.HopField{ {ConsIngress: 41, ConsEgress: 40}, @@ -871,7 +874,7 @@ func TestProcessPkt(t *testing.T) { nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - map[addr.HostSVC][]*net.UDPAddr{ + map[addr.SVC][]*net.UDPAddr{ addr.SvcCS: {&net.UDPAddr{ IP: net.ParseIP("172.0.2.10"), Port: topology.EndhostPort, @@ -887,7 +890,7 @@ func TestProcessPkt(t *testing.T) { spkt.PathType = onehop.PathType spkt.SrcIA = xtest.MustParseIA("1-ff00:0:111") spkt.DstIA = xtest.MustParseIA("1-ff00:0:110") - err := spkt.SetDstAddr(addr.SVCMcast | addr.SvcCS) + err := spkt.SetDstAddr(addr.HostSVC(addr.SvcCS.Multicast())) require.NoError(t, err) dpath := &onehop.Path{ Info: path.InfoField{ @@ -941,7 +944,7 @@ func TestProcessPkt(t *testing.T) { spkt.PathType = onehop.PathType spkt.SrcIA = xtest.MustParseIA("1-ff00:0:110") // sneaky spkt.DstIA = xtest.MustParseIA("1-ff00:0:111") - err := spkt.SetDstAddr(addr.SVCMcast | addr.SvcCS) + err := spkt.SetDstAddr(addr.HostSVC(addr.SvcCS.Multicast())) require.NoError(t, err) dpath := &onehop.Path{ Info: path.InfoField{ @@ -971,7 +974,7 @@ func TestProcessPkt(t *testing.T) { }, nil, mock_router.NewMockBatchConn(ctrl), nil, - map[addr.HostSVC][]*net.UDPAddr{ + map[addr.SVC][]*net.UDPAddr{ addr.SvcCS: {&net.UDPAddr{ IP: net.ParseIP("172.0.2.10"), Port: topology.EndhostPort, @@ -983,7 +986,7 @@ func TestProcessPkt(t *testing.T) { spkt, _ := prepBaseMsg(now) spkt.PathType = scion.PathType spkt.SrcIA = xtest.MustParseIA("1-ff00:0:110") - err := spkt.SetDstAddr(addr.SVCMcast | addr.SvcCS) + err := spkt.SetDstAddr(addr.HostSVC(addr.SvcCS.Multicast())) require.NoError(t, err) dpath := &onehop.Path{ Info: path.InfoField{ @@ -1041,7 +1044,7 @@ func TestProcessPkt(t *testing.T) { spkt.PathType = onehop.PathType spkt.SrcIA = xtest.MustParseIA("1-ff00:0:110") spkt.DstIA = xtest.MustParseIA("1-ff00:0:111") - err := spkt.SetDstAddr(addr.SVCMcast | addr.SvcCS) + err := spkt.SetDstAddr(addr.HostSVC(addr.SvcCS.Multicast())) require.NoError(t, err) dpath := &onehop.Path{ Info: path.InfoField{ @@ -1071,7 +1074,7 @@ func TestProcessPkt(t *testing.T) { "invalid dest": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - map[addr.HostSVC][]*net.UDPAddr{}, + map[addr.SVC][]*net.UDPAddr{}, xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { @@ -1260,7 +1263,8 @@ func prepEpicMsg(t *testing.T, afterProcessing bool, key []byte, PHVF: make([]byte, 4), LHVF: make([]byte, 4), } - require.NoError(t, spkt.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("10.0.200.200").To4()})) + require.NoError(t, spkt.SetSrcAddr(addr.MustParseHost("10.0.200.200"))) + spkt.Path = epicpath return spkt, epicpath, dpath @@ -1287,11 +1291,11 @@ func prepareEpicCrypto(t *testing.T, spkt *slayers.SCION, func toIP(t *testing.T, spkt *slayers.SCION, path path.Path, afterProcessing bool) *ipv4.Message { // Encapsulate in IPv4 - dst := &net.IPAddr{IP: net.ParseIP("10.0.100.100").To4()} + dst := addr.MustParseHost("10.0.100.100") require.NoError(t, spkt.SetDstAddr(dst)) ret := toMsg(t, spkt, path) if afterProcessing { - ret.Addr = &net.UDPAddr{IP: dst.IP, Port: topology.EndhostPort} + ret.Addr = &net.UDPAddr{IP: dst.IP().AsSlice(), Port: topology.EndhostPort} ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil } return ret diff --git a/router/export_test.go b/router/export_test.go index 3a9acc5c8..186bbeede 100644 --- a/router/export_test.go +++ b/router/export_test.go @@ -16,6 +16,7 @@ package router import ( "net" + "net/netip" "golang.org/x/net/ipv4" @@ -36,7 +37,7 @@ func NewDP( linkTypes map[uint16]topology.LinkType, internal BatchConn, internalNextHops map[uint16]*net.UDPAddr, - svc map[addr.HostSVC][]*net.UDPAddr, + svc map[addr.SVC][]*net.UDPAddr, local addr.IA, neighbors map[uint16]addr.IA, key []byte) *DataPlane { @@ -49,7 +50,7 @@ func NewDP( internalNextHops: internalNextHops, svc: &services{m: svc}, internal: internal, - internalIP: &net.IPAddr{IP: net.ParseIP("198.51.100.1")}, + internalIP: netip.MustParseAddr("198.51.100.1"), } if err := dp.SetKey(key); err != nil { panic(err) @@ -74,6 +75,6 @@ func (d *DataPlane) ProcessPkt(ifID uint16, m *ipv4.Message) (ProcessResult, err return ProcessResult{processResult: result}, err } -func ExtractServices(s *services) map[addr.HostSVC][]*net.UDPAddr { +func ExtractServices(s *services) map[addr.SVC][]*net.UDPAddr { return s.m } diff --git a/router/svc.go b/router/svc.go index 98f14042b..a86800b77 100644 --- a/router/svc.go +++ b/router/svc.go @@ -24,14 +24,14 @@ import ( type services struct { mtx sync.Mutex - m map[addr.HostSVC][]*net.UDPAddr + m map[addr.SVC][]*net.UDPAddr } func newServices() *services { - return &services{m: make(map[addr.HostSVC][]*net.UDPAddr)} + return &services{m: make(map[addr.SVC][]*net.UDPAddr)} } -func (s *services) AddSvc(svc addr.HostSVC, a *net.UDPAddr) { +func (s *services) AddSvc(svc addr.SVC, a *net.UDPAddr) { s.mtx.Lock() defer s.mtx.Unlock() @@ -42,7 +42,7 @@ func (s *services) AddSvc(svc addr.HostSVC, a *net.UDPAddr) { s.m[svc] = append(addrs, a) } -func (s *services) DelSvc(svc addr.HostSVC, a *net.UDPAddr) { +func (s *services) DelSvc(svc addr.SVC, a *net.UDPAddr) { s.mtx.Lock() defer s.mtx.Unlock() @@ -56,7 +56,7 @@ func (s *services) DelSvc(svc addr.HostSVC, a *net.UDPAddr) { s.m[svc] = addrs[:len(addrs)-1] } -func (s *services) Any(svc addr.HostSVC) (*net.UDPAddr, bool) { +func (s *services) Any(svc addr.SVC) (*net.UDPAddr, bool) { s.mtx.Lock() defer s.mtx.Unlock() diff --git a/scion-pki/certs/renew.go b/scion-pki/certs/renew.go index 498b6d277..eea541680 100644 --- a/scion-pki/certs/renew.go +++ b/scion-pki/certs/renew.go @@ -505,7 +505,7 @@ The template is expressed in JSON. A valid example:: switch { case len(cas) > 0: for _, ca := range cas { - remote := addr.SvcCS + remote := &snet.SVCAddr{SVC: addr.SvcCS} chain, err := request(ca, remote) if err != nil { continue @@ -647,9 +647,9 @@ func (r *renewer) requestLocal( ) ([]*x509.Certificate, error) { dialer := &grpc.TCPDialer{ - SvcResolver: func(hs addr.HostSVC) []resolver.Address { + SvcResolver: func(hs addr.SVC) []resolver.Address { // Do the SVC resolution - entries, err := r.Daemon.SVCInfo(ctx, []addr.HostSVC{hs}) + entries, err := r.Daemon.SVCInfo(ctx, []addr.SVC{hs}) if err != nil { fmt.Fprintf(r.StdErr, "Failed to resolve SVC address: %s\n", err) return nil @@ -709,10 +709,10 @@ func (r *renewer) requestRemote( Path: path.Dataplane(), NextHop: path.UnderlayNextHop(), } - case addr.HostSVC: + case *snet.SVCAddr: dst = &snet.SVCAddr{ IA: ca, - SVC: r, + SVC: r.SVC, Path: path.Dataplane(), NextHop: path.UnderlayNextHop(), } @@ -960,7 +960,7 @@ type svcRouter struct { Connector daemon.Connector } -func (r svcRouter) GetUnderlay(svc addr.HostSVC) (*net.UDPAddr, error) { +func (r svcRouter) GetUnderlay(svc addr.SVC) (*net.UDPAddr, error) { // XXX(karampok). We need to change the interface to not use TODO context. return daemon.TopoQuerier{Connector: r.Connector}.UnderlayAnycast(context.TODO(), svc) } diff --git a/scion/ping/util.go b/scion/ping/util.go index dd89ffbc8..a9a1d25dd 100644 --- a/scion/ping/util.go +++ b/scion/ping/util.go @@ -15,6 +15,8 @@ package ping import ( + "net/netip" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/snet" @@ -39,15 +41,23 @@ func pack(local, remote *snet.UDPAddr, req snet.SCMPEchoRequest) (*snet.Packet, if isEmpty && !local.IA.Equal(remote.IA) { return nil, serrors.New("no path for remote ISD-AS", "local", local.IA, "remote", remote.IA) } + remoteHostIP, ok := netip.AddrFromSlice(remote.Host.IP) + if !ok { + return nil, serrors.New("invalid remote host IP", "ip", remote.Host.IP) + } + localHostIP, ok := netip.AddrFromSlice(local.Host.IP) + if !ok { + return nil, serrors.New("invalid local host IP", "ip", local.Host.IP) + } pkt := &snet.Packet{ PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: remote.IA, - Host: addr.HostFromIP(remote.Host.IP), + Host: addr.HostIP(remoteHostIP), }, Source: snet.SCIONAddress{ IA: local.IA, - Host: addr.HostFromIP(local.Host.IP), + Host: addr.HostIP(localHostIP), }, Path: remote.Path, Payload: req, diff --git a/scion/showpaths/showpaths.go b/scion/showpaths/showpaths.go index 25475696d..37e328fd3 100644 --- a/scion/showpaths/showpaths.go +++ b/scion/showpaths/showpaths.go @@ -20,7 +20,7 @@ import ( "io" "math" "math/rand" - "net" + "net/netip" "strconv" "strings" "time" @@ -54,7 +54,7 @@ type Path struct { Latency []time.Duration `json:"latency" yaml:"latency"` Status string `json:"status,omitempty" yaml:"status,omitempty"` StatusInfo string `json:"status_info,omitempty" yaml:"status_info,omitempty"` - Local net.IP `json:"local_ip,omitempty" yaml:"local_ip,omitempty"` + Local netip.Addr `json:"local_ip,omitempty" yaml:"local_ip,omitempty"` } // Hop represents an hop on the path. diff --git a/scion/traceroute/traceroute.go b/scion/traceroute/traceroute.go index 8c9c75251..d2805a30b 100644 --- a/scion/traceroute/traceroute.go +++ b/scion/traceroute/traceroute.go @@ -19,6 +19,7 @@ import ( "context" "math/rand" "net" + "net/netip" "time" "github.com/scionproto/scion/pkg/addr" @@ -223,15 +224,24 @@ func (t *tracerouter) probeHop(ctx context.Context, hfIdx uint8, egress bool) (U RTTs: make([]time.Duration, 0, t.probesPerHop), } t.index++ + + remoteHostIP, ok := netip.AddrFromSlice(t.remote.Host.IP) + if !ok { + return Update{}, serrors.New("invalid remote host IP", "ip", t.remote.Host.IP) + } + localHostIP, ok := netip.AddrFromSlice(t.local.Host.IP) + if !ok { + return Update{}, serrors.New("invalid local host IP", "ip", t.local.Host.IP) + } pkt := &snet.Packet{ PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: t.remote.IA, - Host: addr.HostFromIP(t.remote.Host.IP), + Host: addr.HostIP(remoteHostIP), }, Source: snet.SCIONAddress{ IA: t.local.IA, - Host: addr.HostFromIP(t.local.Host.IP), + Host: addr.HostIP(localHostIP), }, Path: alertPath, Payload: snet.SCMPTracerouteRequest{Identifier: t.id}, @@ -310,11 +320,8 @@ func (h scmpHandler) Handle(pkt *snet.Packet) error { h.replies <- reply{ Received: time.Now(), Reply: r, - Remote: snet.SCIONAddress{ - IA: pkt.Source.IA, - Host: pkt.Source.Host.Copy(), - }, - Error: err, + Remote: pkt.Source, + Error: err, } return nil } diff --git a/tools/braccept/cases/bfd.go b/tools/braccept/cases/bfd.go index 2b901bb8d..e178869ca 100644 --- a/tools/braccept/cases/bfd.go +++ b/tools/braccept/cases/bfd.go @@ -102,11 +102,11 @@ func ExternalBFD(artifactsDir string, mac hash.Hash) runner.Case { DstIA: localIA, SrcIA: remoteIA, } - err := scionL.SetSrcAddr(&net.IPAddr{IP: net.IP{192, 168, 13, 3}}) + err := scionL.SetSrcAddr(addr.MustParseHost("192.168.13.3")) if err != nil { panic(err) } - err = scionL.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 13, 2}}) + err = scionL.SetDstAddr(addr.MustParseHost("192.168.13.2")) if err != nil { panic(err) } @@ -134,11 +134,11 @@ func ExternalBFD(artifactsDir string, mac hash.Hash) runner.Case { udp.SrcPort, udp.DstPort = udp.DstPort, udp.SrcPort scionL.DstIA = remoteIA scionL.SrcIA = localIA - err = scionL.SetSrcAddr(&net.IPAddr{IP: net.IP{192, 168, 13, 2}}) + err = scionL.SetSrcAddr(addr.MustParseHost("192.168.13.2")) if err != nil { panic(err) } - err = scionL.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 13, 3}}) + err = scionL.SetDstAddr(addr.MustParseHost("192.168.13.3")) if err != nil { panic(err) } @@ -198,11 +198,11 @@ func InternalBFD(artifactsDir string, mac hash.Hash) runner.Case { SrcIA: localIA, DstIA: localIA, } - err := scionL.SetSrcAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 13}}) + err := scionL.SetSrcAddr(addr.MustParseHost("192.168.0.13")) if err != nil { panic(err) } - err = scionL.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 11}}) + err = scionL.SetDstAddr(addr.MustParseHost("192.168.0.11")) if err != nil { panic(err) } @@ -228,11 +228,11 @@ func InternalBFD(artifactsDir string, mac hash.Hash) runner.Case { ip.SrcIP = net.IP{192, 168, 0, 11} ip.DstIP = net.IP{192, 168, 0, 13} udp.SrcPort, udp.DstPort = udp.DstPort, udp.SrcPort - err = scionL.SetSrcAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 11}}) + err = scionL.SetSrcAddr(addr.MustParseHost("192.168.0.11")) if err != nil { panic(err) } - err = scionL.SetDstAddr(&net.IPAddr{IP: net.IP{192, 168, 0, 13}}) + err = scionL.SetDstAddr(addr.MustParseHost("192.168.0.13")) if err != nil { panic(err) } diff --git a/tools/braccept/cases/child_to_child_xover.go b/tools/braccept/cases/child_to_child_xover.go index 0371d9ffd..74ec549e9 100644 --- a/tools/braccept/cases/child_to_child_xover.go +++ b/tools/braccept/cases/child_to_child_xover.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -107,10 +108,10 @@ func ChildToChildXover(artifactsDir string, mac hash.Hash) runner.Case { Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.5.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.5.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } diff --git a/tools/braccept/cases/child_to_internal.go b/tools/braccept/cases/child_to_internal.go index aadbb33cf..88d5fcdcb 100644 --- a/tools/braccept/cases/child_to_internal.go +++ b/tools/braccept/cases/child_to_internal.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -96,10 +97,10 @@ func ChildToInternalHost(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:1"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.4.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("192.168.0.51")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("192.168.0.51")); err != nil { panic(err) } @@ -203,10 +204,10 @@ func ChildToInternalHostShortcut(artifactsDir string, mac hash.Hash) runner.Case DstIA: xtest.MustParseIA("1-ff00:0:1"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.4.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("192.168.0.51")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("192.168.0.51")); err != nil { panic(err) } @@ -321,10 +322,10 @@ func ChildToInternalParent(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:9"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.4.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("172.16.9.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("172.16.9.1")); err != nil { panic(err) } diff --git a/tools/braccept/cases/child_to_parent.go b/tools/braccept/cases/child_to_parent.go index c09910e52..fb6f24092 100644 --- a/tools/braccept/cases/child_to_parent.go +++ b/tools/braccept/cases/child_to_parent.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -104,10 +105,10 @@ func ChildToParent(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:3"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.4.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.3.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.3.1")); err != nil { panic(err) } diff --git a/tools/braccept/cases/internal_to_child.go b/tools/braccept/cases/internal_to_child.go index a717bcf0b..5587e6141 100644 --- a/tools/braccept/cases/internal_to_child.go +++ b/tools/braccept/cases/internal_to_child.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -100,10 +101,10 @@ func InternalHostToChild(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("192.168.0.51")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("192.168.0.51")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -226,10 +227,10 @@ func InternalParentToChild(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("174.16.9.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("174.16.9.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -353,10 +354,10 @@ func InvalidSrcInternalParentToChild(artifactsDir string, mac hash.Hash) runner. DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("174.16.9.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("174.16.9.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } diff --git a/tools/braccept/cases/jumbo.go b/tools/braccept/cases/jumbo.go index f93faac33..b2695264c 100644 --- a/tools/braccept/cases/jumbo.go +++ b/tools/braccept/cases/jumbo.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -104,10 +105,10 @@ func JumboPacket(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.3.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.3.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } diff --git a/tools/braccept/cases/onehop.go b/tools/braccept/cases/onehop.go index 06ec117b1..56890a613 100644 --- a/tools/braccept/cases/onehop.go +++ b/tools/braccept/cases/onehop.go @@ -24,6 +24,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -78,10 +79,10 @@ func IncomingOneHop(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:1"), Path: ohp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.4.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("192.168.0.71")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("192.168.0.71")); err != nil { panic(err) } @@ -173,10 +174,10 @@ func OutgoingOneHop(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: ohp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("192.168.0.71")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("192.168.0.71")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("172.16.4.1")); err != nil { panic(err) } diff --git a/tools/braccept/cases/parent_to_child.go b/tools/braccept/cases/parent_to_child.go index ebf1d657f..39615aa10 100644 --- a/tools/braccept/cases/parent_to_child.go +++ b/tools/braccept/cases/parent_to_child.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -104,10 +105,10 @@ func ParentToChild(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.3.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.3.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } diff --git a/tools/braccept/cases/parent_to_internal.go b/tools/braccept/cases/parent_to_internal.go index 0026bd121..cdc77ac64 100644 --- a/tools/braccept/cases/parent_to_internal.go +++ b/tools/braccept/cases/parent_to_internal.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -91,10 +92,10 @@ func ParentToInternalHost(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:1"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.3.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.3.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("192.168.0.51")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("192.168.0.51")); err != nil { panic(err) } @@ -205,10 +206,10 @@ func ParentToInternalHostMultiSegment(artifactsDir string, mac hash.Hash) runner DstIA: xtest.MustParseIA("1-ff00:0:1"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.3.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.3.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("192.168.0.51")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("192.168.0.51")); err != nil { panic(err) } diff --git a/tools/braccept/cases/scmp_dest_unreachable.go b/tools/braccept/cases/scmp_dest_unreachable.go index 23009632e..6af4ff1eb 100644 --- a/tools/braccept/cases/scmp_dest_unreachable.go +++ b/tools/braccept/cases/scmp_dest_unreachable.go @@ -95,8 +95,8 @@ func SCMPDestinationUnreachable(artifactsDir string, mac hash.Hash) runner.Case DstIA: xtest.MustParseIA("1-ff00:0:1"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1")} - dstA := addr.HostSVC(15) + srcA := addr.MustParseHost("172.16.3.1") + dstA := addr.HostSVC(addr.SVC(15)) if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } @@ -135,7 +135,7 @@ func SCMPDestinationUnreachable(artifactsDir string, mac hash.Hash) runner.Case if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } diff --git a/tools/braccept/cases/scmp_expired_hop.go b/tools/braccept/cases/scmp_expired_hop.go index 371ff440c..02a886cea 100644 --- a/tools/braccept/cases/scmp_expired_hop.go +++ b/tools/braccept/cases/scmp_expired_hop.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -105,11 +106,11 @@ func SCMPExpiredHop(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1").To4()} + srcA := addr.MustParseHost("172.16.3.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -214,11 +215,11 @@ func SCMPExpiredHopMessageBack(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1").To4()} + srcA := addr.MustParseHost("172.16.3.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -255,7 +256,7 @@ func SCMPExpiredHopMessageBack(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -380,11 +381,11 @@ func SCMPExpiredHopAfterXoverMessageBack(artifactsDir string, mac hash.Hash) run Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1").To4()} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -431,7 +432,7 @@ func SCMPExpiredHopAfterXoverMessageBack(artifactsDir string, mac hash.Hash) run if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -556,11 +557,11 @@ func SCMPExpiredHopAfterXoverConsDirMessageBack(artifactsDir string, mac hash.Ha Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1").To4()} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -607,7 +608,7 @@ func SCMPExpiredHopAfterXoverConsDirMessageBack(artifactsDir string, mac hash.Ha if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -736,11 +737,11 @@ func SCMPExpiredHopAfterXoverInternalMessageBack(artifactsDir string, mac hash.H Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1").To4()} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -781,7 +782,7 @@ func SCMPExpiredHopAfterXoverInternalMessageBack(artifactsDir string, mac hash.H if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -907,11 +908,11 @@ func SCMPExpiredHopAfterXoverInternalConsDirMessageBack( Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1").To4()} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -952,7 +953,7 @@ func SCMPExpiredHopAfterXoverInternalConsDirMessageBack( if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } diff --git a/tools/braccept/cases/scmp_invalid_hop.go b/tools/braccept/cases/scmp_invalid_hop.go index 36b9a9339..c458e1262 100644 --- a/tools/braccept/cases/scmp_invalid_hop.go +++ b/tools/braccept/cases/scmp_invalid_hop.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -97,11 +98,11 @@ func SCMPInvalidHopParentToParent(artifactsDir string, mac hash.Hash) runner.Cas DstIA: xtest.MustParseIA("1-ff00:0:9"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1")} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -146,7 +147,7 @@ func SCMPInvalidHopParentToParent(artifactsDir string, mac hash.Hash) runner.Cas if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -258,11 +259,11 @@ func SCMPInvalidHopChildToChild(artifactsDir string, mac hash.Hash) runner.Case DstIA: xtest.MustParseIA("1-ff00:0:5"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1")} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -307,7 +308,7 @@ func SCMPInvalidHopChildToChild(artifactsDir string, mac hash.Hash) runner.Case if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } diff --git a/tools/braccept/cases/scmp_invalid_ia.go b/tools/braccept/cases/scmp_invalid_ia.go index d5115bf67..f501ff308 100644 --- a/tools/braccept/cases/scmp_invalid_ia.go +++ b/tools/braccept/cases/scmp_invalid_ia.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -99,11 +100,11 @@ func SCMPInvalidSrcIAInternalHostToChild(artifactsDir string, mac hash.Hash) run DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("192.168.0.51")} + srcA := addr.MustParseHost("192.168.0.51") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -136,7 +137,7 @@ func SCMPInvalidSrcIAInternalHostToChild(artifactsDir string, mac hash.Hash) run if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -246,11 +247,11 @@ func SCMPInvalidDstIAInternalHostToChild(artifactsDir string, mac hash.Hash) run DstIA: xtest.MustParseIA("1-ff00:0:1"), // == local IA, invalid Dst IA Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("192.168.0.51")} + srcA := addr.MustParseHost("192.168.0.51") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -283,7 +284,7 @@ func SCMPInvalidDstIAInternalHostToChild(artifactsDir string, mac hash.Hash) run if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -397,11 +398,11 @@ func SCMPInvalidSrcIAChildToParent(artifactsDir string, mac hash.Hash) runner.Ca DstIA: xtest.MustParseIA("1-ff00:0:3"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.4.1")} + srcA := addr.MustParseHost("172.16.4.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.3.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.3.1")); err != nil { panic(err) } @@ -434,7 +435,7 @@ func SCMPInvalidSrcIAChildToParent(artifactsDir string, mac hash.Hash) runner.Ca if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -553,11 +554,11 @@ func SCMPInvalidDstIAChildToParent(artifactsDir string, mac hash.Hash) runner.Ca DstIA: xtest.MustParseIA("1-ff00:0:1"), // == local IA, invalid Dst IA Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.4.1")} + srcA := addr.MustParseHost("172.16.4.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.3.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.3.1")); err != nil { panic(err) } @@ -590,7 +591,7 @@ func SCMPInvalidDstIAChildToParent(artifactsDir string, mac hash.Hash) runner.Ca if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } diff --git a/tools/braccept/cases/scmp_invalid_mac.go b/tools/braccept/cases/scmp_invalid_mac.go index 42d7334e9..ce94c1c20 100644 --- a/tools/braccept/cases/scmp_invalid_mac.go +++ b/tools/braccept/cases/scmp_invalid_mac.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -103,11 +104,11 @@ func SCMPBadMAC(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1")} + srcA := addr.MustParseHost("172.16.3.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -144,7 +145,7 @@ func SCMPBadMAC(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -259,11 +260,11 @@ func SCMPBadMACInternal(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1")} + srcA := addr.MustParseHost("172.16.3.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -300,7 +301,7 @@ func SCMPBadMACInternal(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } diff --git a/tools/braccept/cases/scmp_invalid_pkt.go b/tools/braccept/cases/scmp_invalid_pkt.go index ec2c76d0d..bf61dcd9c 100644 --- a/tools/braccept/cases/scmp_invalid_pkt.go +++ b/tools/braccept/cases/scmp_invalid_pkt.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -92,11 +93,11 @@ func SCMPBadPktLen(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1").To4()} + srcA := addr.MustParseHost("172.16.3.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -138,7 +139,7 @@ func SCMPBadPktLen(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -246,11 +247,11 @@ func SCMPQuoteCut(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1").To4()} + srcA := addr.MustParseHost("172.16.3.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -296,7 +297,7 @@ func SCMPQuoteCut(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -407,11 +408,11 @@ func NoSCMPReplyForSCMPError(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1").To4()} + srcA := addr.MustParseHost("172.16.3.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } diff --git a/tools/braccept/cases/scmp_invalid_segment_change.go b/tools/braccept/cases/scmp_invalid_segment_change.go index 36dd425ae..20d52c2e6 100644 --- a/tools/braccept/cases/scmp_invalid_segment_change.go +++ b/tools/braccept/cases/scmp_invalid_segment_change.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -106,11 +107,11 @@ func SCMPParentToParentXover(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:9"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1")} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -155,7 +156,7 @@ func SCMPParentToParentXover(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -281,11 +282,11 @@ func SCMPParentToChildXover(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:8"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1")} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -330,7 +331,7 @@ func SCMPParentToChildXover(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -458,11 +459,11 @@ func SCMPChildToParentXover(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:9"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1")} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -508,7 +509,7 @@ func SCMPChildToParentXover(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -636,11 +637,11 @@ func SCMPInternalXover(artifactsDir string, mac hash.Hash) runner.Case { Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.168.0.14").To4()} + srcA := addr.MustParseHost("172.168.0.14") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - dstA := &net.IPAddr{IP: net.ParseIP("172.16.4.1").To4()} + dstA := addr.MustParseHost("172.16.4.1") if err := scionL.SetDstAddr(dstA); err != nil { panic(err) } @@ -687,7 +688,7 @@ func SCMPInternalXover(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } diff --git a/tools/braccept/cases/scmp_invalid_segment_change_local.go b/tools/braccept/cases/scmp_invalid_segment_change_local.go index dd019f912..e0198c686 100644 --- a/tools/braccept/cases/scmp_invalid_segment_change_local.go +++ b/tools/braccept/cases/scmp_invalid_segment_change_local.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -106,11 +107,11 @@ func SCMPParentToParentLocalXover(artifactsDir string, mac hash.Hash) runner.Cas DstIA: xtest.MustParseIA("1-ff00:0:3"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1")} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -155,7 +156,7 @@ func SCMPParentToParentLocalXover(artifactsDir string, mac hash.Hash) runner.Cas if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -281,11 +282,11 @@ func SCMPParentToChildLocalXover(artifactsDir string, mac hash.Hash) runner.Case DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1")} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -330,7 +331,7 @@ func SCMPParentToChildLocalXover(artifactsDir string, mac hash.Hash) runner.Case if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -458,11 +459,11 @@ func SCMPChildToParentLocalXover(artifactsDir string, mac hash.Hash) runner.Case DstIA: xtest.MustParseIA("1-ff00:0:3"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.5.1")} + srcA := addr.MustParseHost("172.16.5.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -508,7 +509,7 @@ func SCMPChildToParentLocalXover(artifactsDir string, mac hash.Hash) runner.Case if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } diff --git a/tools/braccept/cases/scmp_traceroute.go b/tools/braccept/cases/scmp_traceroute.go index 271358d4b..6242efe1e 100644 --- a/tools/braccept/cases/scmp_traceroute.go +++ b/tools/braccept/cases/scmp_traceroute.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" @@ -95,11 +96,11 @@ func SCMPTracerouteIngress(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:2"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.4.1").To4()} + srcA := addr.MustParseHost("172.16.4.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.2.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.2.1")); err != nil { panic(err) } @@ -131,7 +132,7 @@ func SCMPTracerouteIngress(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -237,11 +238,11 @@ func SCMPTracerouteIngressWithSPAO(artifactsDir string, mac hash.Hash) runner.Ca DstIA: xtest.MustParseIA("1-ff00:0:2"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.4.1").To4()} + srcA := addr.MustParseHost("172.16.4.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.2.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.2.1")); err != nil { panic(err) } @@ -311,7 +312,7 @@ func SCMPTracerouteIngressWithSPAO(artifactsDir string, mac hash.Hash) runner.Ca if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -440,11 +441,11 @@ func SCMPTracerouteIngressConsDir(artifactsDir string, mac hash.Hash) runner.Cas DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1").To4()} + srcA := addr.MustParseHost("172.16.3.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -481,7 +482,7 @@ func SCMPTracerouteIngressConsDir(artifactsDir string, mac hash.Hash) runner.Cas if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -585,11 +586,11 @@ func SCMPTracerouteEgress(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:3"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.4.1").To4()} + srcA := addr.MustParseHost("172.16.4.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.2.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.2.1")); err != nil { panic(err) } @@ -621,7 +622,7 @@ func SCMPTracerouteEgress(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -724,11 +725,11 @@ func SCMPTracerouteEgressConsDir(artifactsDir string, mac hash.Hash) runner.Case DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1").To4()} + srcA := addr.MustParseHost("172.16.3.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -765,7 +766,7 @@ func SCMPTracerouteEgressConsDir(artifactsDir string, mac hash.Hash) runner.Case if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -884,11 +885,11 @@ func SCMPTracerouteEgressAfterXover(artifactsDir string, mac hash.Hash) runner.C Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.8.1").To4()} + srcA := addr.MustParseHost("172.16.8.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - dstA := &net.IPAddr{IP: net.ParseIP("172.16.4.1").To4()} + dstA := addr.MustParseHost("172.16.4.1") if err := scionL.SetDstAddr(dstA); err != nil { panic(err) } @@ -922,7 +923,7 @@ func SCMPTracerouteEgressAfterXover(artifactsDir string, mac hash.Hash) runner.C if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -1024,11 +1025,11 @@ func SCMPTracerouteInternal(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("192.168.0.51").To4()} + srcA := addr.MustParseHost("192.168.0.51") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -1061,7 +1062,7 @@ func SCMPTracerouteInternal(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } diff --git a/tools/braccept/cases/scmp_unknown_hop.go b/tools/braccept/cases/scmp_unknown_hop.go index af7fdf278..f4c48b4d4 100644 --- a/tools/braccept/cases/scmp_unknown_hop.go +++ b/tools/braccept/cases/scmp_unknown_hop.go @@ -23,6 +23,7 @@ import ( "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/slayers" @@ -104,11 +105,11 @@ func SCMPUnknownHop(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:4"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1").To4()} + srcA := addr.MustParseHost("172.16.3.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.4.1").To4()}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { panic(err) } @@ -145,7 +146,7 @@ func SCMPUnknownHop(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } @@ -262,8 +263,8 @@ func SCMPUnknownHopEgress(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:f1"), Path: sp, } - srcA := &net.IPAddr{IP: net.ParseIP("172.16.3.1")} - dstA := &net.IPAddr{IP: net.ParseIP("174.16.16.1")} + srcA := addr.MustParseHost("172.16.3.1") + dstA := addr.MustParseHost("174.16.16.1") if err := scionL.SetSrcAddr(srcA); err != nil { panic(err) } @@ -304,7 +305,7 @@ func SCMPUnknownHopEgress(artifactsDir string, mac hash.Hash) runner.Case { if err := scionL.SetDstAddr(srcA); err != nil { panic(err) } - intlA := &net.IPAddr{IP: net.IP{192, 168, 0, 11}} + intlA := addr.MustParseHost("192.168.0.11") if err := scionL.SetSrcAddr(intlA); err != nil { panic(err) } diff --git a/tools/braccept/cases/svc.go b/tools/braccept/cases/svc.go index 913255fe2..220522a03 100644 --- a/tools/braccept/cases/svc.go +++ b/tools/braccept/cases/svc.go @@ -95,10 +95,10 @@ func SVC(artifactsDir string, mac hash.Hash) runner.Case { DstIA: xtest.MustParseIA("1-ff00:0:1"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP("172.16.4.1")}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.4.1")); err != nil { panic(err) } - if err := scionL.SetDstAddr(addr.HostSVCFromString("CS")); err != nil { + if err := scionL.SetDstAddr(addr.HostSVC(addr.SvcCS)); err != nil { panic(err) } scionudp := &slayers.UDP{} diff --git a/tools/braccept/runner/BUILD.bazel b/tools/braccept/runner/BUILD.bazel index 18ef04a7a..4c66b4c9a 100644 --- a/tools/braccept/runner/BUILD.bazel +++ b/tools/braccept/runner/BUILD.bazel @@ -27,6 +27,7 @@ go_test( srcs = ["compare_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/addr:go_default_library", "//pkg/private/util:go_default_library", "//pkg/private/xtest:go_default_library", "//pkg/scrypto:go_default_library", diff --git a/tools/braccept/runner/compare_test.go b/tools/braccept/runner/compare_test.go index a827dd07e..d2f8b327d 100644 --- a/tools/braccept/runner/compare_test.go +++ b/tools/braccept/runner/compare_test.go @@ -15,13 +15,13 @@ package runner import ( - "net" "testing" "time" "github.com/google/gopacket" "github.com/stretchr/testify/assert" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/scrypto" @@ -93,10 +93,10 @@ func prepareSCION(t *testing.T, diff string) gopacket.Packet { DstIA: xtest.MustParseIA("1-ff00:0:3"), Path: sp, } - if err := scionL.SetSrcAddr(&net.IPAddr{IP: net.ParseIP(diff)}); err != nil { + if err := scionL.SetSrcAddr(addr.MustParseHost(diff)); err != nil { assert.NoError(t, err) } - if err := scionL.SetDstAddr(&net.IPAddr{IP: net.ParseIP("174.16.3.1")}); err != nil { + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.3.1")); err != nil { assert.NoError(t, err) } diff --git a/tools/end2end/main.go b/tools/end2end/main.go index 4db1e04f5..1018f2247 100644 --- a/tools/end2end/main.go +++ b/tools/end2end/main.go @@ -23,6 +23,7 @@ import ( "flag" "fmt" "net" + "net/netip" "os" "time" @@ -331,15 +332,24 @@ func (c *client) ping(ctx context.Context, n int, path snet.Path) error { Port: topology.EndhostPort, } } + + remoteHostIP, ok := netip.AddrFromSlice(remote.Host.IP) + if !ok { + return serrors.New("invalid remote host IP", "ip", remote.Host.IP) + } + localHostIP, ok := netip.AddrFromSlice(integration.Local.Host.IP) + if !ok { + return serrors.New("invalid local host IP", "ip", integration.Local.Host.IP) + } pkt := &snet.Packet{ PacketInfo: snet.PacketInfo{ Destination: snet.SCIONAddress{ IA: remote.IA, - Host: addr.HostFromIP(remote.Host.IP), + Host: addr.HostIP(remoteHostIP), }, Source: snet.SCIONAddress{ IA: integration.Local.IA, - Host: addr.HostFromIP(integration.Local.Host.IP), + Host: addr.HostIP(localHostIP), }, Path: remote.Path, Payload: snet.UDPPayload{ diff --git a/tools/pktgen/cmd/pktgen/BUILD.bazel b/tools/pktgen/cmd/pktgen/BUILD.bazel index 4636177a8..d03afafbc 100644 --- a/tools/pktgen/cmd/pktgen/BUILD.bazel +++ b/tools/pktgen/cmd/pktgen/BUILD.bazel @@ -10,6 +10,7 @@ go_library( importpath = "github.com/scionproto/scion/tools/pktgen/cmd/pktgen", visibility = ["//visibility:private"], deps = [ + "//pkg/addr:go_default_library", "//pkg/daemon:go_default_library", "//pkg/log:go_default_library", "//pkg/private/common:go_default_library", diff --git a/tools/pktgen/cmd/pktgen/main.go b/tools/pktgen/cmd/pktgen/main.go index 0c2cec256..d56d951ac 100644 --- a/tools/pktgen/cmd/pktgen/main.go +++ b/tools/pktgen/cmd/pktgen/main.go @@ -18,13 +18,14 @@ import ( "context" "encoding/json" "fmt" - "net" + "net/netip" "os" "path/filepath" "github.com/google/gopacket" "github.com/spf13/cobra" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/daemon" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/common" @@ -155,10 +156,14 @@ func run(cfg flags, dst *snet.UDPAddr) error { scionLayer.SrcIA = localIA scionLayer.DstIA = path.Destination() scionLayer.Path = decPath - if err := scionLayer.SetDstAddr(&net.IPAddr{IP: dst.Host.IP, Zone: dst.Host.Zone}); err != nil { + dstHostIP, ok := netip.AddrFromSlice(dst.Host.IP) + if !ok { + return serrors.New("invalid destination host IP", "ip", dst.Host.IP) + } + if err := scionLayer.SetDstAddr(addr.HostIP(dstHostIP)); err != nil { return serrors.WrapStr("setting SCION dest address", err) } - if err := scionLayer.SetSrcAddr(&net.IPAddr{IP: localIP}); err != nil { + if err := scionLayer.SetSrcAddr(addr.HostIP(localIP)); err != nil { return serrors.WrapStr("setting SCION source address", err) } scionudpLayer := &slayers.UDP{} @@ -184,15 +189,18 @@ func run(cfg flags, dst *snet.UDPAddr) error { return nil } -func resolveLocal(dst *snet.UDPAddr) (net.IP, error) { +func resolveLocal(dst *snet.UDPAddr) (netip.Addr, error) { target := dst.Host.IP if dst.NextHop != nil { target = dst.NextHop.IP } - localIP, err := addrutil.ResolveLocal(target) + resolvedIP, err := addrutil.ResolveLocal(target) if err != nil { - return nil, serrors.WrapStr("resolving local address", err) - + return netip.Addr{}, serrors.WrapStr("resolving local address", err) + } + localIP, ok := netip.AddrFromSlice(resolvedIP) + if !ok { + return netip.Addr{}, serrors.New("invalid local IP", "ip", resolvedIP) } return localIP, nil } From 00835ed735ebd246d9f6dbaece0319f898325ac9 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Wed, 12 Jul 2023 16:31:07 +0200 Subject: [PATCH 036/255] deps: change rules_antlr fork (#4362) The fork of rules_antlr that we depend on has disappeared https://github.com/artisoft-io We switch to another fork that contains the same changes that artisoft-io had. --- WORKSPACE | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 9936bb501..856854ca8 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -125,9 +125,11 @@ rules_pkg_dependencies() # Antlr rules http_archive( name = "rules_antlr", - sha256 = "234c401cfabab78f2d7f5589239d98f16f04338768a72888f660831964948ab1", + # XXX(roosd): This hash is not guaranteed to be stable by GitHub. + # See: https://github.blog/changelog/2023-01-30-git-archive-checksums-may-change + sha256 = "8d7c457cc266965bdcf7e85aa349d2f851b772a55877354d9ae92ada7a62c857", strip_prefix = "rules_antlr-0.6.0", - urls = ["https://github.com/artisoft-io/rules_antlr/archive/0.6.0.tar.gz"], + urls = ["https://github.com/bacek/rules_antlr/archive/refs/tags/0.6.0.tar.gz"], ) load("@rules_antlr//antlr:repositories.bzl", "rules_antlr_dependencies") From b0cc226ab9bc0e740d9dbb9266f4afa5758edaff Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Thu, 13 Jul 2023 17:42:23 +0200 Subject: [PATCH 037/255] build: generate docs with write_source_files (#4357) Use write_source_files to generate the docs. The write_source_files comes with automatic tests that the generated files are up to date. We create a wrapper in tools/lint which checks that the generated files are up to date if we run bazel test with --config=lint. `make lint` checks that the `write_all` target is up to date with all the additional targets to run. --- BUILD.bazel | 16 ++++-- Makefile | 14 +++-- WORKSPACE | 13 ++++- doc/command/BUILD.bazel | 23 +++----- doc/command/defs.bzl | 52 ------------------- doc/command/scion-pki/scion-pki.rst | 0 .../scion-pki/scion-pki_certificate.rst | 0 .../scion-pki_certificate_create.rst | 0 .../scion-pki_certificate_fingerprint.rst | 0 .../scion-pki_certificate_inspect.rst | 0 .../scion-pki/scion-pki_certificate_match.rst | 0 .../scion-pki_certificate_match_private.rst | 0 .../scion-pki/scion-pki_certificate_renew.rst | 0 .../scion-pki/scion-pki_certificate_sign.rst | 0 .../scion-pki_certificate_validate.rst | 0 .../scion-pki_certificate_verify.rst | 0 .../scion-pki_certificate_verify_ca.rst | 0 .../scion-pki/scion-pki_completion.rst | 0 .../scion-pki/scion-pki_completion_bash.rst | 0 .../scion-pki/scion-pki_completion_fish.rst | 0 .../scion-pki_completion_powershell.rst | 0 .../scion-pki/scion-pki_completion_zsh.rst | 0 doc/command/scion-pki/scion-pki_key.rst | 0 .../scion-pki/scion-pki_key_fingerprint.rst | 0 doc/command/scion-pki/scion-pki_key_match.rst | 0 .../scion-pki_key_match_certificate.rst | 0 .../scion-pki/scion-pki_key_private.rst | 0 .../scion-pki/scion-pki_key_public.rst | 0 .../scion-pki/scion-pki_key_symmetric.rst | 0 doc/command/scion-pki/scion-pki_trc.rst | 0 .../scion-pki/scion-pki_trc_combine.rst | 0 .../scion-pki/scion-pki_trc_extract.rst | 0 .../scion-pki_trc_extract_certificates.rst | 0 .../scion-pki_trc_extract_payload.rst | 0 .../scion-pki/scion-pki_trc_format.rst | 0 .../scion-pki/scion-pki_trc_inspect.rst | 0 .../scion-pki/scion-pki_trc_payload.rst | 0 doc/command/scion-pki/scion-pki_trc_sign.rst | 0 .../scion-pki/scion-pki_trc_verify.rst | 0 doc/command/scion-pki/scion-pki_version.rst | 0 doc/command/scion/scion.rst | 0 doc/command/scion/scion_address.rst | 0 doc/command/scion/scion_completion.rst | 0 doc/command/scion/scion_completion_bash.rst | 0 doc/command/scion/scion_completion_fish.rst | 0 .../scion/scion_completion_powershell.rst | 0 doc/command/scion/scion_completion_zsh.rst | 0 doc/command/scion/scion_ping.rst | 0 doc/command/scion/scion_showpaths.rst | 0 doc/command/scion/scion_traceroute.rst | 0 doc/command/scion/scion_version.rst | 0 tools/lint/write_source_files.bzl | 27 ++++++++++ tools/lint/write_source_files_sync | 32 ++++++++++++ 53 files changed, 101 insertions(+), 76 deletions(-) delete mode 100644 doc/command/defs.bzl mode change 100755 => 100644 doc/command/scion-pki/scion-pki.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate_create.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate_fingerprint.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate_inspect.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate_match.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate_match_private.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate_renew.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate_sign.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate_validate.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate_verify.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_certificate_verify_ca.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_completion.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_completion_bash.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_completion_fish.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_completion_powershell.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_completion_zsh.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_key.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_key_fingerprint.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_key_match.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_key_match_certificate.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_key_private.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_key_public.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_key_symmetric.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_trc.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_trc_combine.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_trc_extract.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_trc_extract_certificates.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_trc_extract_payload.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_trc_format.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_trc_inspect.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_trc_payload.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_trc_sign.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_trc_verify.rst mode change 100755 => 100644 doc/command/scion-pki/scion-pki_version.rst mode change 100755 => 100644 doc/command/scion/scion.rst mode change 100755 => 100644 doc/command/scion/scion_address.rst mode change 100755 => 100644 doc/command/scion/scion_completion.rst mode change 100755 => 100644 doc/command/scion/scion_completion_bash.rst mode change 100755 => 100644 doc/command/scion/scion_completion_fish.rst mode change 100755 => 100644 doc/command/scion/scion_completion_powershell.rst mode change 100755 => 100644 doc/command/scion/scion_completion_zsh.rst mode change 100755 => 100644 doc/command/scion/scion_ping.rst mode change 100755 => 100644 doc/command/scion/scion_showpaths.rst mode change 100755 => 100644 doc/command/scion/scion_traceroute.rst mode change 100755 => 100644 doc/command/scion/scion_version.rst create mode 100644 tools/lint/write_source_files.bzl create mode 100755 tools/lint/write_source_files_sync diff --git a/BUILD.bazel b/BUILD.bazel index f48ed70cd..6e8445b1d 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -3,6 +3,7 @@ load("@bazel_gazelle//:def.bzl", "gazelle") load("@rules_pkg//:pkg.bzl", "pkg_tar") load("@io_bazel_rules_go//go:def.bzl", "nogo") load("//tools/lint:go_config.bzl", "go_lint_config") +load("//tools/lint:write_source_files.bzl", "write_source_files") load("//tools/lint/python:flake8_config.bzl", "flake8_lint_config") load("//:nogo.bzl", "nogo_deps") load("@com_github_bazelbuild_buildtools//buildifier:def.bzl", "buildifier") @@ -115,11 +116,18 @@ buildifier( mode = "check", ) -# Runs all update_src targets in this Workspace. +# Runs all update_src targets in this Workspace. Currently, generating the +# OpenAPI specs is the last target that depends on update_src. Eventually, +# this should be transitioned to write_all_source_files below. updatesrc_update_all( name = "update_all", - targets_to_run = [ - "//doc/command:copy_scion", - "//doc/command:copy_scion-pki", +) + +# Runs all write_source_files targets in this Workspace. To update the list run +# bazel run @com_github_bazelbuild_buildtools//buildozer -- --root_dir $PWD "add additional_update_targets $( bazel query 'filter("^.*[^\d]$", kind(_write_source_file, //...)) except //:write_all_source_files' | tr '\n' ' ')" //:write_all_source_files +write_source_files( + name = "write_all_source_files", + additional_update_targets = [ + "//doc/command:write_files", ], ) diff --git a/Makefile b/Makefile index 355e27d70..81dcdb505 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all antlr bazel clean docker-images gazelle go-mod-tidy licenses mocks protobuf scion-topo test test-integration +.PHONY: all antlr bazel clean docker-images gazelle go-mod-tidy licenses mocks protobuf scion-topo test test-integration write_all_source_files GAZELLE_MODE?=fix GAZELLE_DIRS=. @@ -10,7 +10,7 @@ build: bazel # Use NOTPARALLEL to force correct order. # Note: From GNU make 4.4, this still allows building any other targets (e.g. lint) in parallel. .NOTPARALLEL: all -all: go_deps.bzl protobuf mocks gazelle licenses build antlr +all: go_deps.bzl protobuf mocks gazelle licenses build antlr write_all_source_files clean: bazel clean @@ -66,6 +66,10 @@ licenses: antlr: antlr/generate.sh $(GAZELLE_MODE) +write_all_source_files: + bazel run //:write_all_source_files + bazel run //:update_all + .PHONY: lint lint-bazel lint-bazel-buildifier lint-doc lint-doc-mdlint lint-go lint-go-bazel lint-go-gazelle lint-go-golangci lint-go-semgrep lint-openapi lint-openapi-spectral lint-protobuf lint-protobuf-buf # Enable --keep-going if all goals specified on the command line match the pattern "lint%" @@ -95,12 +99,16 @@ lint-go-semgrep: @if [ -t 1 ]; then tty=true; else tty=false; fi; \ tools/quiet docker run --tty=$$tty --rm -v "${PWD}:/src" returntocorp/semgrep@sha256:3bef9d533a44e6448c43ac38159d61fad89b4b57f63e565a8a55ca265273f5ba semgrep --config=/src/tools/lint/semgrep --error -lint-bazel: lint-bazel-buildifier +lint-bazel: lint-bazel-buildifier lint-bazel-writeall lint-bazel-buildifier: $(info ==> $@) @tools/quiet bazel run --config=quiet //:buildifier_check +lint-bazel-writeall: + $(info ==> $@) + @tools/quiet ./tools/lint/write_source_files_sync + lint-protobuf: lint-protobuf-buf lint-protobuf-buf: diff --git a/WORKSPACE b/WORKSPACE index 856854ca8..a19a966fe 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -29,6 +29,17 @@ lint_setup({ "flake8": "//:flake8_lint_config", }) +http_archive( + name = "aspect_bazel_lib", + sha256 = "e3151d87910f69cf1fc88755392d7c878034a69d6499b287bcfc00b1cf9bb415", + strip_prefix = "bazel-lib-1.32.1", + url = "https://github.com/aspect-build/bazel-lib/archive/refs/tags/v1.32.1.tar.gz", +) + +load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies") + +aspect_bazel_lib_dependencies() + # Bazel rules for Golang http_archive( name = "io_bazel_rules_go", @@ -61,7 +72,7 @@ http_archive( ], ) -load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository") +load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") go_rules_dependencies() diff --git a/doc/command/BUILD.bazel b/doc/command/BUILD.bazel index 07a2d41c8..bc941e780 100644 --- a/doc/command/BUILD.bazel +++ b/doc/command/BUILD.bazel @@ -1,18 +1,9 @@ -load(":defs.bzl", "recursive_copy_output") +load("//tools/lint:write_source_files.bzl", "write_source_files") -exports_files( - ["defs.bzl"], - ["//visibility:public"], -) - -recursive_copy_output( - name = "copy_scion", - input_dir = "//scion/cmd/scion:gendocs", - output_dir = ":scion", -) - -recursive_copy_output( - name = "copy_scion-pki", - input_dir = "//scion-pki/cmd/scion-pki:gendocs", - output_dir = ":scion-pki", +write_source_files( + name = "write_files", + files = { + "scion": "//scion/cmd/scion:gendocs", + "scion-pki": "//scion-pki/cmd/scion-pki:gendocs", + }, ) diff --git a/doc/command/defs.bzl b/doc/command/defs.bzl deleted file mode 100644 index 86e201f7b..000000000 --- a/doc/command/defs.bzl +++ /dev/null @@ -1,52 +0,0 @@ -def _recursive_copy_output_impl(ctx): - generated_dir = ctx.file.input_dir - output_dir = ctx.file.output_dir - - # Make sure that the directories are available to the update script. - runfiles = ctx.runfiles(files = [generated_dir, output_dir]) - - # Declare the update script + specify it's content - update_sh = ctx.actions.declare_file( - ctx.label.name + "_update.sh", - ) - extra_script = "" - if ctx.attr.file_transformation: - extra_script = "\nfor FILE in {output_dir}/*; do {file_transformation} ; done".format( - output_dir = output_dir.short_path, - file_transformation = ctx.attr.file_transformation, - ) - ctx.actions.write( - output = update_sh, - content = """ -#!/usr/bin/env bash -runfiles_dir=$(pwd) -# When run from a test, build workspace directory is not set. The -# source copy just happens in the sandbox. -if [[ ! -z "${BUILD_WORKSPACE_DIRECTORY}" ]]; then - cd "${BUILD_WORKSPACE_DIRECTORY}" -fi -""" + "\nrm -rf {output_dir}/*\ncp -rf -t {output_dir} $(readlink \"${{runfiles_dir}}/{generated_dir}\")/*\nchmod -R 0755 {output_dir}".format( - generated_dir = generated_dir.short_path, - output_dir = output_dir.short_path, - ) + extra_script, - is_executable = True, - ) - return [DefaultInfo(executable = update_sh, runfiles = runfiles)] - -recursive_copy_output = rule( - implementation = _recursive_copy_output_impl, - attrs = { - "input_dir": attr.label( - mandatory = True, - allow_single_file = True, - ), - "output_dir": attr.label( - mandatory = True, - allow_single_file = True, - ), - "file_transformation": attr.string( - doc = "Input the function of a for loop which iterates over every file generated", - ), - }, - executable = True, -) diff --git a/doc/command/scion-pki/scion-pki.rst b/doc/command/scion-pki/scion-pki.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate.rst b/doc/command/scion-pki/scion-pki_certificate.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate_create.rst b/doc/command/scion-pki/scion-pki_certificate_create.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate_fingerprint.rst b/doc/command/scion-pki/scion-pki_certificate_fingerprint.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate_inspect.rst b/doc/command/scion-pki/scion-pki_certificate_inspect.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate_match.rst b/doc/command/scion-pki/scion-pki_certificate_match.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate_match_private.rst b/doc/command/scion-pki/scion-pki_certificate_match_private.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate_renew.rst b/doc/command/scion-pki/scion-pki_certificate_renew.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate_sign.rst b/doc/command/scion-pki/scion-pki_certificate_sign.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate_validate.rst b/doc/command/scion-pki/scion-pki_certificate_validate.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate_verify.rst b/doc/command/scion-pki/scion-pki_certificate_verify.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_certificate_verify_ca.rst b/doc/command/scion-pki/scion-pki_certificate_verify_ca.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_completion.rst b/doc/command/scion-pki/scion-pki_completion.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_completion_bash.rst b/doc/command/scion-pki/scion-pki_completion_bash.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_completion_fish.rst b/doc/command/scion-pki/scion-pki_completion_fish.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_completion_powershell.rst b/doc/command/scion-pki/scion-pki_completion_powershell.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_completion_zsh.rst b/doc/command/scion-pki/scion-pki_completion_zsh.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_key.rst b/doc/command/scion-pki/scion-pki_key.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_key_fingerprint.rst b/doc/command/scion-pki/scion-pki_key_fingerprint.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_key_match.rst b/doc/command/scion-pki/scion-pki_key_match.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_key_match_certificate.rst b/doc/command/scion-pki/scion-pki_key_match_certificate.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_key_private.rst b/doc/command/scion-pki/scion-pki_key_private.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_key_public.rst b/doc/command/scion-pki/scion-pki_key_public.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_key_symmetric.rst b/doc/command/scion-pki/scion-pki_key_symmetric.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_trc.rst b/doc/command/scion-pki/scion-pki_trc.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_trc_combine.rst b/doc/command/scion-pki/scion-pki_trc_combine.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_trc_extract.rst b/doc/command/scion-pki/scion-pki_trc_extract.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_trc_extract_certificates.rst b/doc/command/scion-pki/scion-pki_trc_extract_certificates.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_trc_extract_payload.rst b/doc/command/scion-pki/scion-pki_trc_extract_payload.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_trc_format.rst b/doc/command/scion-pki/scion-pki_trc_format.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_trc_inspect.rst b/doc/command/scion-pki/scion-pki_trc_inspect.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_trc_payload.rst b/doc/command/scion-pki/scion-pki_trc_payload.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_trc_sign.rst b/doc/command/scion-pki/scion-pki_trc_sign.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_trc_verify.rst b/doc/command/scion-pki/scion-pki_trc_verify.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion-pki/scion-pki_version.rst b/doc/command/scion-pki/scion-pki_version.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion.rst b/doc/command/scion/scion.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion_address.rst b/doc/command/scion/scion_address.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion_completion.rst b/doc/command/scion/scion_completion.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion_completion_bash.rst b/doc/command/scion/scion_completion_bash.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion_completion_fish.rst b/doc/command/scion/scion_completion_fish.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion_completion_powershell.rst b/doc/command/scion/scion_completion_powershell.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion_completion_zsh.rst b/doc/command/scion/scion_completion_zsh.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion_ping.rst b/doc/command/scion/scion_ping.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion_showpaths.rst b/doc/command/scion/scion_showpaths.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion_traceroute.rst b/doc/command/scion/scion_traceroute.rst old mode 100755 new mode 100644 diff --git a/doc/command/scion/scion_version.rst b/doc/command/scion/scion_version.rst old mode 100755 new mode 100644 diff --git a/tools/lint/write_source_files.bzl b/tools/lint/write_source_files.bzl new file mode 100644 index 000000000..4fda04a36 --- /dev/null +++ b/tools/lint/write_source_files.bzl @@ -0,0 +1,27 @@ +load("@aspect_bazel_lib//lib:write_source_files.bzl", _write_source_files = "write_source_files") + +def write_source_files(name, **kwargs): + """A wrapper around the aspect bazel lib write_source_files function. + + Args: + name: The name of the rule + **kwargs: The arguments as defined in the write_sources_files function. + """ + + tags = kwargs.get("tags", []) + if "write_src" not in tags: + tags = tags + ["write_src"] + kwargs["tags"] = tags + + suggested_target = kwargs.get("suggested_update_target", None) + if suggested_target == None: + kwargs["suggested_update_target"] = "//:write_all_source_files" + + visibility = kwargs.get("visibility", None) + if visibility == None: + kwargs["visibility"] = ["//visibility:public"] + + _write_source_files( + name = name, + **kwargs + ) diff --git a/tools/lint/write_source_files_sync b/tools/lint/write_source_files_sync new file mode 100755 index 000000000..86e52d7ab --- /dev/null +++ b/tools/lint/write_source_files_sync @@ -0,0 +1,32 @@ +#!/bin/bash + +# This script ensures that the "additional_update_targets" entry of the +# "//:write_all_source_files_source_files" target in the root BUILD.bazel file is up to date. +# This catches the case that a new write_source_file target is added but not +# registered in //:write_all_source_files_source_files. +# +# We use bazel query to find all the targets. However, the //:write_all_source_files_source_files +# is also detected. Thus, we need to strip it out. Buildozer is then used to +# write a new BUILD.bazel file with the all targets registered. +# +# The result is diffed against the current BUILD.bazel file. If there is a +# difference, the script fails and the developer needs to update the target. + + +root_dir="$(bazel info workspace 2> /dev/null)" + +ret=0 +diff -Nu3 $root_dir/BUILD.bazel <(bazel run @com_github_bazelbuild_buildtools//buildozer -- --root_dir $root_dir --stdout "add additional_update_targets $(bazel query 'filter("^.*[^\d]$", kind(_write_source_file, //...)) except //:write_all_source_files' | tr '\n' ' ')" //:write_all_source_files) || ret=$? +if [[ $ret -ne 0 ]] && [ "${CI+x}" == x ]; then + annotate=$(cat < Date: Tue, 18 Jul 2023 12:45:47 +0200 Subject: [PATCH 038/255] python: update pyyaml to 6.0.0 (#4367) Update the pyyaml dependency to 6.0.0. 6.0.0 includes [this commit](https://github.com/yaml/pyyaml/commit/a6d384c52ea54ded80df27032c7b6d3a98b0c2fa) that removes the use of the [deprecated](https://setuptools.pypa.io/en/latest/userguide/declarative_config.html#metadata) `license_file` field in the setup.cfg. This addresses the following warning: ``` The license_file parameter is deprecated, use license_files instead. By 2023-Oct-30, you need to update your project and remove deprecated calls or your builds will no longer be supported. See https://setuptools.pypa.io/en/latest/userguide/declarative_config.html for details. ``` --- tools/env/pip3/requirements.in | 2 +- tools/env/pip3/requirements.txt | 63 +++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/tools/env/pip3/requirements.in b/tools/env/pip3/requirements.in index ed2c6af11..4cb789098 100644 --- a/tools/env/pip3/requirements.in +++ b/tools/env/pip3/requirements.in @@ -1,5 +1,5 @@ toml==0.10.2 -pyyaml==5.4.1 +pyyaml==6.0.0 plumbum==1.6.9 supervisor==4.2.1 supervisor-wildcards==0.1.3 diff --git a/tools/env/pip3/requirements.txt b/tools/env/pip3/requirements.txt index 449970e8d..f7e050319 100644 --- a/tools/env/pip3/requirements.txt +++ b/tools/env/pip3/requirements.txt @@ -8,28 +8,47 @@ plumbum==1.6.9 \ --hash=sha256:16b9e19d96c80f2e9d051ef5f04927b834a6ac0ce5d2768eb8662b5cd53e43df \ --hash=sha256:91418dcc66b58ab9d2e3b04b3d1e0d787dc45923154fb8b4a826bd9316dba0d6 # via -r tools/env/pip3/requirements.in -pyyaml==5.4.1 \ - --hash=sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf \ - --hash=sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696 \ - --hash=sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393 \ - --hash=sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77 \ - --hash=sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922 \ - --hash=sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5 \ - --hash=sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8 \ - --hash=sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10 \ - --hash=sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc \ - --hash=sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018 \ - --hash=sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e \ - --hash=sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253 \ - --hash=sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183 \ - --hash=sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb \ - --hash=sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185 \ - --hash=sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db \ - --hash=sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46 \ - --hash=sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b \ - --hash=sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63 \ - --hash=sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df \ - --hash=sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc +pyyaml==6.0.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 # via -r tools/env/pip3/requirements.in six==1.15.0 \ --hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \ From ab37c7af9060b949ba35de8f24f510af9b0817c6 Mon Sep 17 00:00:00 2001 From: rohrerj <26304001+rohrerj@users.noreply.github.com> Date: Tue, 18 Jul 2023 14:52:07 +0200 Subject: [PATCH 039/255] router: perf improvement by async packet processing (#4351) Restructure the border router's packet processing loop into receiver, processing and forwarders goroutines. This is implementation part one of three described in the design document (github.com/scionproto/scion/pull/4339, doc/dev/design/BorderRouter.rst). --- router/BUILD.bazel | 3 + router/cmd/router/main.go | 4 +- router/dataplane.go | 492 ++++++++++++++++++++++-------- router/dataplane_internal_test.go | 461 ++++++++++++++++++++++++++++ router/dataplane_test.go | 37 +-- router/export_test.go | 11 +- router/metrics.go | 13 +- 7 files changed, 868 insertions(+), 153 deletions(-) create mode 100644 router/dataplane_internal_test.go diff --git a/router/BUILD.bazel b/router/BUILD.bazel index 57fae70cd..27ad3eb3e 100644 --- a/router/BUILD.bazel +++ b/router/BUILD.bazel @@ -34,12 +34,14 @@ go_library( "@com_github_google_gopacket//layers:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", + "@org_golang_x_net//ipv4:go_default_library", ], ) go_test( name = "go_default_test", srcs = [ + "dataplane_internal_test.go", "dataplane_test.go", "export_test.go", "svc_test.go", @@ -48,6 +50,7 @@ go_test( deps = [ "//pkg/addr:go_default_library", "//pkg/experimental/epic:go_default_library", + "//pkg/private/serrors:go_default_library", "//pkg/private/util:go_default_library", "//pkg/private/xtest:go_default_library", "//pkg/scrypto:go_default_library", diff --git a/router/cmd/router/main.go b/router/cmd/router/main.go index 5a5c2c634..ccc765f93 100644 --- a/router/cmd/router/main.go +++ b/router/cmd/router/main.go @@ -121,7 +121,9 @@ func realMain(ctx context.Context) error { }) g.Go(func() error { defer log.HandlePanic() - if err := dp.DataPlane.Run(errCtx); err != nil { + runConfig := &router.RunConfig{} + runConfig.LoadDefaults() + if err := dp.DataPlane.Run(errCtx, runConfig); err != nil { return serrors.WrapStr("running dataplane", err) } return nil diff --git a/router/dataplane.go b/router/dataplane.go index 81592f3cd..60f2001c5 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -1,4 +1,5 @@ // Copyright 2020 Anapaya Systems +// Copyright 2023 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,17 +23,19 @@ import ( "errors" "fmt" "hash" + "hash/fnv" "math/big" "net" "net/netip" + "runtime" "strconv" "sync" - "syscall" "time" "github.com/google/gopacket" "github.com/google/gopacket/layers" "github.com/prometheus/client_golang/prometheus" + "golang.org/x/net/ipv4" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" @@ -49,16 +52,12 @@ import ( "github.com/scionproto/scion/pkg/slayers/path/scion" "github.com/scionproto/scion/pkg/spao" "github.com/scionproto/scion/private/topology" - "github.com/scionproto/scion/private/underlay/conn" underlayconn "github.com/scionproto/scion/private/underlay/conn" "github.com/scionproto/scion/router/bfd" "github.com/scionproto/scion/router/control" ) const ( - // Number of packets to read in a single ReadBatch call. - inputBatchCnt = 64 - // TODO(karampok). Investigate whether that value should be higher. In // theory, PayloadLen in SCION header is 16 bits long, supporting a maximum // payload size of 64KB. At the moment we are limited by Ethernet size @@ -96,6 +95,7 @@ type BatchConn interface { // Currently, only the following features are supported: // - initializing connections; MUST be done prior to calling Run type DataPlane struct { + interfaces map[uint16]BatchConn external map[uint16]BatchConn linkTypes map[uint16]topology.LinkType neighborIAs map[uint16]addr.IA @@ -110,6 +110,10 @@ type DataPlane struct { running bool Metrics *Metrics forwardingMetrics map[uint16]forwardingMetrics + + // The pool that stores all the packet buffers as described in the design document. See + // https://github.com/scionproto/scion/blob/master/doc/dev/design/BorderRouter.rst + packetPool chan []byte } var ( @@ -203,6 +207,10 @@ func (d *DataPlane) AddInternalInterface(conn BatchConn, ip net.IP) error { if d.internal != nil { return alreadySet } + if d.interfaces == nil { + d.interfaces = make(map[uint16]BatchConn) + } + d.interfaces[0] = conn d.internal = conn var ok bool d.internalIP, ok = netip.AddrFromSlice(ip) @@ -230,6 +238,10 @@ func (d *DataPlane) AddExternalInterface(ifID uint16, conn BatchConn) error { if d.external == nil { d.external = make(map[uint16]BatchConn) } + if d.interfaces == nil { + d.interfaces = make(map[uint16]BatchConn) + } + d.interfaces[ifID] = conn d.external[ifID] = conn return nil } @@ -446,88 +458,45 @@ func (d *DataPlane) AddNextHopBFD(ifID uint16, src, dst *net.UDPAddr, cfg contro return d.addBFDController(ifID, s, cfg, m) } -// Run starts running the dataplane. Note that configuration is not possible -// after calling this method. -func (d *DataPlane) Run(ctx context.Context) error { +type RunConfig struct { + NumProcessors int + BatchSize int +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + +func (d *DataPlane) Run(ctx context.Context, cfg *RunConfig) error { d.mtx.Lock() d.running = true - d.initMetrics() - read := func(ingressID uint16, rd BatchConn) { - - msgs := conn.NewReadMessages(inputBatchCnt) - for _, msg := range msgs { - msg.Buffers[0] = make([]byte, bufSize) - } - writeMsgs := make(underlayconn.Messages, 1) - writeMsgs[0].Buffers = make([][]byte, 1) + processorQueueSize := max( + len(d.interfaces)*cfg.BatchSize/cfg.NumProcessors, + cfg.BatchSize) - processor := newPacketProcessor(d, ingressID) - var scmpErr scmpError - for d.running { - pkts, err := rd.ReadBatch(msgs) - if err != nil { - log.Debug("Failed to read batch", "err", err) - // error metric - continue - } - if pkts == 0 { - continue - } - for _, p := range msgs[:pkts] { - // input metric - inputCounters := d.forwardingMetrics[ingressID] - inputCounters.InputPacketsTotal.Inc() - inputCounters.InputBytesTotal.Add(float64(p.N)) - - srcAddr := p.Addr.(*net.UDPAddr) - result, err := processor.processPkt(p.Buffers[0][:p.N], srcAddr) - - switch { - case err == nil: - case errors.As(err, &scmpErr): - if !scmpErr.TypeCode.InfoMsg() { - log.Debug("SCMP", "err", scmpErr, "dst_addr", p.Addr) - } - // SCMP go back the way they came. - result.OutAddr = srcAddr - result.OutConn = rd - default: - log.Debug("Error processing packet", "err", err) - inputCounters.DroppedPacketsTotal.Inc() - continue - } - if result.OutConn == nil { // e.g. BFD case no message is forwarded - continue - } + d.initPacketPool(cfg, processorQueueSize) + procQs, fwQs := initQueues(cfg, d.interfaces, processorQueueSize) - // Write to OutConn; drop the packet if this would block. - // Use WriteBatch because it's the only available function that - // supports MSG_DONTWAIT. - writeMsgs[0].Buffers[0] = result.OutPkt - writeMsgs[0].Addr = nil - if result.OutAddr != nil { // don't assign directly to net.Addr, typed nil! - writeMsgs[0].Addr = result.OutAddr - } - - _, err = result.OutConn.WriteBatch(writeMsgs, syscall.MSG_DONTWAIT) - if err != nil { - var errno syscall.Errno - if !errors.As(err, &errno) || - !(errno == syscall.EAGAIN || errno == syscall.EWOULDBLOCK) { - log.Debug("Error writing packet", "err", err) - // error metric - } - inputCounters.DroppedPacketsTotal.Inc() - continue - } - // ok metric - outputCounters := d.forwardingMetrics[result.EgressID] - outputCounters.OutputPacketsTotal.Inc() - outputCounters.OutputBytesTotal.Add(float64(len(result.OutPkt))) - } - } + for ifID, conn := range d.interfaces { + go func(ifID uint16, conn BatchConn) { + defer log.HandlePanic() + d.runReceiver(ifID, conn, cfg, procQs) + }(ifID, conn) + go func(ifID uint16, conn BatchConn) { + defer log.HandlePanic() + d.runForwarder(ifID, conn, cfg, fwQs[ifID]) + }(ifID, conn) + } + for i := 0; i < cfg.NumProcessors; i++ { + go func(i int) { + defer log.HandlePanic() + d.runProcessor(i, procQs[i], fwQs) + }(i) } for k, v := range d.bfdSessions { @@ -538,23 +507,278 @@ func (d *DataPlane) Run(ctx context.Context) error { } }(k, v) } - for ifID, v := range d.external { - go func(i uint16, c BatchConn) { - defer log.HandlePanic() - read(i, c) - }(ifID, v) - } - go func(c BatchConn) { - defer log.HandlePanic() - read(0, c) - }(d.internal) d.mtx.Unlock() - <-ctx.Done() return nil } +// loadDefaults sets the default configuration for the number of +// processors and the batch size +func (r *RunConfig) LoadDefaults() { + // TODO(rohrerj) move this logic to configuration in configuration PR + r.NumProcessors = runtime.GOMAXPROCS(0) + r.BatchSize = 256 + +} + +// initializePacketPool calculates the size of the packet pool based on the +// current dataplane settings and allocates all the buffers +func (d *DataPlane) initPacketPool(cfg *RunConfig, processorQueueSize int) { + poolSize := len(d.interfaces)*cfg.BatchSize + + cfg.NumProcessors*(processorQueueSize+1) + + len(d.interfaces)*(2*cfg.BatchSize) + + log.Debug("Initialize packet pool of size", "poolSize", poolSize) + d.packetPool = make(chan []byte, poolSize) + for i := 0; i < poolSize; i++ { + d.packetPool <- make([]byte, bufSize) + } +} + +// initializes the processing routines and forwarders queues +func initQueues(cfg *RunConfig, interfaces map[uint16]BatchConn, + processorQueueSize int) ([]chan packet, map[uint16]chan packet) { + + procQs := make([]chan packet, cfg.NumProcessors) + for i := 0; i < cfg.NumProcessors; i++ { + procQs[i] = make(chan packet, processorQueueSize) + } + fwQs := make(map[uint16]chan packet) + for ifID := range interfaces { + fwQs[ifID] = make(chan packet, cfg.BatchSize) + } + return procQs, fwQs +} + +type packet struct { + // The source address. Will be set by the receiver + srcAddr *net.UDPAddr + // The address to where we are forwarding the packet. + // Will be set by the processing routine + dstAddr *net.UDPAddr + // The ingress on which this packet arrived. Will be + // set by the receiver + ingress uint16 + rawPacket []byte +} + +func (d *DataPlane) runReceiver(ifID uint16, conn BatchConn, cfg *RunConfig, + procQs []chan packet) { + + log.Debug("Run receiver for", "interface", ifID) + randomValue := make([]byte, 16) + if _, err := rand.Read(randomValue); err != nil { + panic("Error while generating random value") + } + + msgs := underlayconn.NewReadMessages(cfg.BatchSize) + numReusable := 0 // unused buffers from previous loop + metrics := d.forwardingMetrics[ifID] + flowIDBuffer := make([]byte, 3) + hasher := fnv.New32a() + + enqueueForProcessing := func(pkt ipv4.Message) { + metrics.InputPacketsTotal.Inc() + metrics.InputBytesTotal.Add(float64(pkt.N)) + + srcAddr := pkt.Addr.(*net.UDPAddr) + + procID, err := computeProcID(pkt.Buffers[0], + cfg.NumProcessors, randomValue, flowIDBuffer, hasher) + if err != nil { + log.Debug("Error while computing procID", "err", err) + d.returnPacketToPool(pkt.Buffers[0]) + metrics.DroppedPacketsInvalid.Inc() + return + } + outPkt := packet{ + rawPacket: pkt.Buffers[0][:pkt.N], + ingress: ifID, + srcAddr: srcAddr, + } + select { + case procQs[procID] <- outPkt: + default: + d.returnPacketToPool(pkt.Buffers[0]) + metrics.DroppedPacketsBusyProcessor.Inc() + } + } + + for d.running { + // collect packets + for i := 0; i < cfg.BatchSize-numReusable; i++ { + p := <-d.packetPool + msgs[i].Buffers[0] = p + } + + // read batch + numPkts, err := conn.ReadBatch(msgs) + numReusable = len(msgs) - numPkts + if err != nil { + log.Debug("Error while reading batch", "interfaceID", ifID, "err", err) + continue + } + for _, pkt := range msgs[:numPkts] { + enqueueForProcessing(pkt) + } + + } +} + +func computeProcID(data []byte, numProcRoutines int, randomValue []byte, + flowIDBuffer []byte, hasher hash.Hash32) (uint32, error) { + + if len(data) < slayers.CmnHdrLen { + return 0, serrors.New("Packet is too short") + } + dstHostAddrLen := slayers.AddrType(data[9] >> 4 & 0xf).Length() + srcHostAddrLen := slayers.AddrType(data[9] & 0xf).Length() + addrHdrLen := 2*addr.IABytes + srcHostAddrLen + dstHostAddrLen + if len(data) < slayers.CmnHdrLen+addrHdrLen { + return 0, serrors.New("Packet is too short") + } + copy(flowIDBuffer[0:3], data[1:4]) + flowIDBuffer[0] &= 0xF // the left 4 bits don't belong to the flowID + + hasher.Reset() + hasher.Write(randomValue) + hasher.Write(flowIDBuffer[:]) + hasher.Write(data[slayers.CmnHdrLen : slayers.CmnHdrLen+addrHdrLen]) + return hasher.Sum32() % uint32(numProcRoutines), nil +} + +func (d *DataPlane) returnPacketToPool(pkt []byte) { + d.packetPool <- pkt[:cap(pkt)] +} + +func (d *DataPlane) runProcessor(id int, q <-chan packet, + fwQs map[uint16]chan packet) { + + log.Debug("Initialize processor with", "id", id) + processor := newPacketProcessor(d) + var scmpErr scmpError + for d.running { + p, ok := <-q + if !ok { + continue + } + metrics := d.forwardingMetrics[p.ingress] + result, err := processor.processPkt(p.rawPacket, p.srcAddr, p.ingress) + metrics.ProcessedPackets.Inc() + egress := result.EgressID + switch { + case err == nil: + case errors.As(err, &scmpErr): + if !scmpErr.TypeCode.InfoMsg() { + log.Debug("SCMP", "err", scmpErr) + } + default: + log.Debug("Error processing packet", "err", err) + metrics.DroppedPacketsInvalid.Inc() + d.returnPacketToPool(p.rawPacket) + continue + } + if result.OutPkt == nil { // e.g. BFD case no message is forwarded + d.returnPacketToPool(p.rawPacket) + continue + } + fwCh, ok := fwQs[egress] + if !ok { + log.Debug("Error determining forwarder. Egress is invalid", "egress", egress) + metrics.DroppedPacketsInvalid.Inc() + d.returnPacketToPool(p.rawPacket) + continue + } + p.rawPacket = result.OutPkt + p.dstAddr = result.OutAddr + + select { + case fwCh <- p: + default: + d.returnPacketToPool(p.rawPacket) + metrics.DroppedPacketsBusyForwarder.Inc() + } + + } +} + +func (d *DataPlane) runForwarder(ifID uint16, conn BatchConn, + cfg *RunConfig, c <-chan packet) { + + log.Debug("Initialize forwarder for", "interface", ifID) + writeMsgs := make(underlayconn.Messages, cfg.BatchSize) + for i := range writeMsgs { + writeMsgs[i].Buffers = make([][]byte, 1) + } + metrics := d.forwardingMetrics[ifID] + + remaining := 0 + for d.running { + available := readUpTo(c, cfg.BatchSize-remaining, remaining == 0, + writeMsgs[remaining:]) + available += remaining + written, _ := conn.WriteBatch(writeMsgs[:available], 0) + if written < 0 { + // WriteBatch returns -1 on error, we just consider this as + // 0 packets written + written = 0 + } + writtenBytes := 0 + for i := range writeMsgs[:written] { + writtenBytes += len(writeMsgs[i].Buffers[0]) + d.returnPacketToPool(writeMsgs[i].Buffers[0]) + } + metrics.OutputPacketsTotal.Add(float64(written)) + metrics.OutputBytesTotal.Add(float64(writtenBytes)) + + if written != available { + metrics.DroppedPacketsInvalid.Inc() + d.returnPacketToPool(writeMsgs[written].Buffers[0]) + remaining = available - written - 1 + for i := 0; i < remaining; i++ { + writeMsgs[i].Buffers[0] = writeMsgs[i+written+1].Buffers[0] + writeMsgs[i].Addr = writeMsgs[i+written+1].Addr + } + } else { + remaining = 0 + } + } +} + +func readUpTo(c <-chan packet, n int, needsBlocking bool, msg []ipv4.Message) int { + assign := func(p packet, m *ipv4.Message) { + m.Buffers[0] = p.rawPacket + m.Addr = nil + if p.dstAddr != nil { + m.Addr = p.dstAddr + } + } + i := 0 + if needsBlocking { + p, ok := <-c + if !ok { + return i + } + assign(p, &msg[i]) + i++ + } + + for ; i < n; i++ { + select { + case p, ok := <-c: + if !ok { + return i + } + assign(p, &msg[i]) + default: + return i + } + + } + return i +} + // initMetrics initializes the metrics related to packet forwarding. The // counters are already instantiated for all the relevant interfaces so this // will not have to be repeated during packet forwarding. @@ -573,17 +797,15 @@ func (d *DataPlane) initMetrics() { type processResult struct { EgressID uint16 - OutConn BatchConn OutAddr *net.UDPAddr OutPkt []byte } -func newPacketProcessor(d *DataPlane, ingressID uint16) *scionPacketProcessor { +func newPacketProcessor(d *DataPlane) *scionPacketProcessor { p := &scionPacketProcessor{ - d: d, - ingressID: ingressID, - buffer: gopacket.NewSerializeBuffer(), - mac: d.macFactory(), + d: d, + buffer: gopacket.NewSerializeBuffer(), + mac: d.macFactory(), macBuffers: macBuffers{ scionInput: make([]byte, path.MACBufferSize), epicInput: make([]byte, libepic.MACBufferSize), @@ -600,6 +822,8 @@ func newPacketProcessor(d *DataPlane, ingressID uint16) *scionPacketProcessor { func (p *scionPacketProcessor) reset() error { p.rawPkt = nil + p.srcAddr = nil + p.ingressID = 0 //p.scionLayer // cannot easily be reset p.path = nil p.hopField = path.HopField{} @@ -618,13 +842,14 @@ func (p *scionPacketProcessor) reset() error { } func (p *scionPacketProcessor) processPkt(rawPkt []byte, - srcAddr *net.UDPAddr) (processResult, error) { + srcAddr *net.UDPAddr, ingressID uint16) (processResult, error) { if err := p.reset(); err != nil { return processResult{}, err } p.rawPkt = rawPkt p.srcAddr = srcAddr + p.ingressID = ingressID // parse SCION header and skip extensions; var err error @@ -842,7 +1067,12 @@ func (p *scionPacketProcessor) packSCMP( } rawSCMP, err := p.prepareSCMP(typ, code, scmpP, cause) - return processResult{OutPkt: rawSCMP}, err + if rawSCMP != nil { + p.rawPkt = p.rawPkt[:len(rawSCMP)] + copy(p.rawPkt, rawSCMP) + } + + return processResult{OutPkt: p.rawPkt, EgressID: p.ingressID, OutAddr: p.srcAddr}, err } func (p *scionPacketProcessor) parsePath() (processResult, error) { @@ -1282,19 +1512,17 @@ func (p *scionPacketProcessor) process() (processResult, error) { if r, err := p.handleIngressRouterAlert(); err != nil { return r, err } - // Inbound: pkts destined to the local IA. if p.scionLayer.DstIA == p.d.localIA { a, r, err := p.resolveInbound() if err != nil { return r, err } - return processResult{OutConn: p.d.internal, OutAddr: a, OutPkt: p.rawPkt}, nil + return processResult{OutAddr: a, OutPkt: p.rawPkt}, nil } // Outbound: pkts leaving the local IA. // BRTransit: pkts leaving from the same BR different interface. - if p.path.IsXover() { if r, err := p.doXover(); err != nil { return r, err @@ -1319,18 +1547,16 @@ func (p *scionPacketProcessor) process() (processResult, error) { if r, err := p.validateEgressUp(); err != nil { return r, err } - egressID := p.egressInterface() - if c, ok := p.d.external[egressID]; ok { + if _, ok := p.d.external[egressID]; ok { if err := p.processEgress(); err != nil { return processResult{}, err } - return processResult{EgressID: egressID, OutConn: c, OutPkt: p.rawPkt}, nil + return processResult{EgressID: egressID, OutPkt: p.rawPkt}, nil } - // ASTransit: pkts leaving from another AS BR. if a, ok := p.d.internalNextHops[egressID]; ok { - return processResult{OutConn: p.d.internal, OutAddr: a, OutPkt: p.rawPkt}, nil + return processResult{OutAddr: a, OutPkt: p.rawPkt}, nil } errCode := slayers.SCMPCodeUnknownHopFieldEgress if !p.infoField.ConsDir { @@ -1388,15 +1614,8 @@ func (p *scionPacketProcessor) processOHP() (processResult, error) { if err := updateSCIONLayer(p.rawPkt, s, p.buffer); err != nil { return processResult{}, err } - // OHP should always be directed to the correct BR. - if c, ok := p.d.external[ohp.FirstHop.ConsEgress]; ok { - // buffer should already be correct - return processResult{EgressID: ohp.FirstHop.ConsEgress, OutConn: c, OutPkt: p.rawPkt}, - nil - } - // TODO parameter problem invalid interface - return processResult{}, serrors.WithCtx(cannotRoute, "type", "ohp", - "egress", ohp.FirstHop.ConsEgress, "consDir", ohp.Info.ConsDir) + return processResult{EgressID: ohp.FirstHop.ConsEgress, OutPkt: p.rawPkt}, + nil } // OHP entering our IA @@ -1428,7 +1647,7 @@ func (p *scionPacketProcessor) processOHP() (processResult, error) { if err != nil { return processResult{}, err } - return processResult{OutConn: p.d.internal, OutAddr: a, OutPkt: p.rawPkt}, nil + return processResult{OutAddr: a, OutPkt: p.rawPkt}, nil } func (d *DataPlane) resolveLocalDst(s slayers.SCION) (*net.UDPAddr, error) { @@ -1873,26 +2092,39 @@ func nextHdr(layer gopacket.DecodingLayer) slayers.L4ProtocolType { // forwardingMetrics contains the subset of Metrics relevant for forwarding, // instantiated with some interface-specific labels. type forwardingMetrics struct { - InputBytesTotal prometheus.Counter - OutputBytesTotal prometheus.Counter - InputPacketsTotal prometheus.Counter - OutputPacketsTotal prometheus.Counter - DroppedPacketsTotal prometheus.Counter + InputBytesTotal prometheus.Counter + OutputBytesTotal prometheus.Counter + InputPacketsTotal prometheus.Counter + OutputPacketsTotal prometheus.Counter + DroppedPacketsInvalid prometheus.Counter + DroppedPacketsBusyProcessor prometheus.Counter + DroppedPacketsBusyForwarder prometheus.Counter + ProcessedPackets prometheus.Counter } func initForwardingMetrics(metrics *Metrics, labels prometheus.Labels) forwardingMetrics { c := forwardingMetrics{ - InputBytesTotal: metrics.InputBytesTotal.With(labels), - InputPacketsTotal: metrics.InputPacketsTotal.With(labels), - OutputBytesTotal: metrics.OutputBytesTotal.With(labels), - OutputPacketsTotal: metrics.OutputPacketsTotal.With(labels), - DroppedPacketsTotal: metrics.DroppedPacketsTotal.With(labels), - } + InputBytesTotal: metrics.InputBytesTotal.With(labels), + InputPacketsTotal: metrics.InputPacketsTotal.With(labels), + OutputBytesTotal: metrics.OutputBytesTotal.With(labels), + OutputPacketsTotal: metrics.OutputPacketsTotal.With(labels), + ProcessedPackets: metrics.ProcessedPackets.With(labels), + } + labels["reason"] = "invalid" + c.DroppedPacketsInvalid = metrics.DroppedPacketsTotal.With(labels) + labels["reason"] = "busy_processor" + c.DroppedPacketsBusyProcessor = metrics.DroppedPacketsTotal.With(labels) + labels["reason"] = "busy_forwarder" + c.DroppedPacketsBusyForwarder = metrics.DroppedPacketsTotal.With(labels) + c.InputBytesTotal.Add(0) c.InputPacketsTotal.Add(0) c.OutputBytesTotal.Add(0) c.OutputPacketsTotal.Add(0) - c.DroppedPacketsTotal.Add(0) + c.DroppedPacketsInvalid.Add(0) + c.DroppedPacketsBusyProcessor.Add(0) + c.DroppedPacketsBusyForwarder.Add(0) + c.ProcessedPackets.Add(0) return c } diff --git a/router/dataplane_internal_test.go b/router/dataplane_internal_test.go new file mode 100644 index 000000000..60291aaa4 --- /dev/null +++ b/router/dataplane_internal_test.go @@ -0,0 +1,461 @@ +// Copyright 2023 ETH Zurich +// +// 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 router + +import ( + "bytes" + "encoding/binary" + "hash/fnv" + "math/rand" + "net" + "net/netip" + "reflect" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/google/gopacket" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/private/util" + "github.com/scionproto/scion/pkg/private/xtest" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/pkg/slayers/path/scion" + underlayconn "github.com/scionproto/scion/private/underlay/conn" + "github.com/scionproto/scion/router/mock_router" +) + +// TestReceiver sets up a mocked batchConn, starts the receiver that reads from +// this batchConn and forwards it to the processing routines channels. We verify +// by directly reading from the processing routine channels that we received +// the same number of packets as the receiver received. +func TestReceiver(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + dp := &DataPlane{Metrics: metrics} + counter := 0 + mInternal := mock_router.NewMockBatchConn(ctrl) + done := make(chan bool) + mInternal.EXPECT().ReadBatch(gomock.Any()).DoAndReturn( + func(m underlayconn.Messages) (int, error) { + for i := 0; i < 10; i++ { + payload := bytes.Repeat([]byte("actualpayloadbytes"), i) + raw := serializedBaseMsg(t, payload, 0) + copy(m[i].Buffers[0], raw) + m[i].N = len(raw) + m[i].Addr = &net.UDPAddr{IP: net.IP{10, 0, 200, 200}} + counter++ + } + return 10, nil + }, + ).Times(2) + mInternal.EXPECT().ReadBatch(gomock.Any()).DoAndReturn( + func(m underlayconn.Messages) (int, error) { + dp.running = false + done <- true + return 0, nil + }, + ).Times(1) + + _ = dp.AddInternalInterface(mInternal, net.IP{}) + + runConfig := &RunConfig{ + NumProcessors: 1, + BatchSize: 64, + } + dp.initPacketPool(runConfig, 64) + procCh, _ := initQueues(runConfig, dp.interfaces, 64) + initialPoolSize := len(dp.packetPool) + dp.running = true + dp.initMetrics() + go func() { + dp.runReceiver(0, dp.internal, runConfig, procCh) + }() + ptrMap := make(map[uintptr]struct{}) + for i := 0; i < 21; i++ { + select { + case pkt := <-procCh[0]: + // make sure that the pool size has decreased + assert.Greater(t, initialPoolSize, len(dp.packetPool)) + // make sure that the packet has the right size + assert.Equal(t, 84+i%10*18, len(pkt.rawPacket)) + // make sure that the source address was set correctly + assert.Equal(t, net.UDPAddr{IP: net.IP{10, 0, 200, 200}}, *pkt.srcAddr) + // make sure that the received pkt buffer has not been seen before + ptr := reflect.ValueOf(pkt.rawPacket).Pointer() + assert.NotContains(t, ptrMap, ptr) + ptrMap[ptr] = struct{}{} + case <-time.After(50 * time.Millisecond): + // make sure that the processing routine received exactly 20 messages + if i != 20 { + t.Fail() + dp.running = false + } + } + } + <-done + // make sure that the packet pool has the expected size after the test + assert.Equal(t, initialPoolSize-runConfig.BatchSize-20, len(dp.packetPool)) +} + +// TestForwarder sets up a mocked batchConn, starts the forwarder that will write to +// this batchConn and forwards some packets to the channel of the forwarder. We then +// verify that the forwarder has sent all the packets, no packets got reordered +// and that the buffers have been returned to the buffer pool. +func TestForwarder(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + done := make(chan struct{}) + prepareDP := func(ctrl *gomock.Controller) *DataPlane { + ret := &DataPlane{Metrics: metrics} + + mInternal := mock_router.NewMockBatchConn(ctrl) + totalCount := 0 + expectedPktId := byte(0) + mInternal.EXPECT().WriteBatch(gomock.Any(), 0).DoAndReturn( + func(ms underlayconn.Messages, flags int) (int, error) { + if totalCount == 255 { + return 0, nil + } + for i, m := range ms { + totalCount++ + // 1/5 of the packets (randomly chosen) are errors + if rand.Intn(5) == 0 { + expectedPktId++ + ms = ms[:i] + break + } else { + pktId := m.Buffers[0][0] + if !assert.Equal(t, expectedPktId, pktId) { + t.Log("packets got reordered.", + "expected", expectedPktId, "got", pktId, "ms", ms) + } + if totalCount <= 100 { + assert.NotNil(t, m.Addr) + } else { + // stronger check than assert.Nil + assert.True(t, m.Addr == nil) + } + expectedPktId++ + } + } + if totalCount == 255 { + ret.running = false + done <- struct{}{} + } + if len(ms) == 0 { + return 0, nil + } + + return len(ms), nil + }).AnyTimes() + _ = ret.AddInternalInterface(mInternal, net.IP{}) + return ret + } + dp := prepareDP(ctrl) + runConfig := &RunConfig{ + NumProcessors: 20, + BatchSize: 64, + } + dp.initPacketPool(runConfig, 64) + _, fwCh := initQueues(runConfig, dp.interfaces, 64) + initialPoolSize := len(dp.packetPool) + dp.running = true + dp.initMetrics() + go dp.runForwarder(0, dp.internal, runConfig, fwCh[0]) + + dstAddr := &net.UDPAddr{IP: net.IP{10, 0, 200, 200}} + for i := 0; i < 255; i++ { + pkt := <-dp.packetPool + assert.NotEqual(t, initialPoolSize, len(dp.packetPool)) + pkt[0] = byte(i) + if i == 100 { + dstAddr = nil + } + select { + case fwCh[0] <- packet{ + srcAddr: nil, + dstAddr: dstAddr, + ingress: 0, + rawPacket: pkt[:1], + }: + case <-done: + } + + } + select { + case <-done: + time.Sleep(100 * time.Millisecond) + assert.Equal(t, initialPoolSize, len(dp.packetPool)) + case <-time.After(100 * time.Millisecond): + t.Fail() + dp.running = false + } +} + +func TestComputeProcId(t *testing.T) { + randomValue := []byte{1, 2, 3, 4} + numProcs := 10000 + + // this function returns the procID by using the slayers.SCION serialization + // implementation + referenceHash := func(s *slayers.SCION) uint32 { + flowBuf := make([]byte, 4) + binary.BigEndian.PutUint32(flowBuf, s.FlowID) + flowBuf[0] &= 0xF + tmpBuffer := make([]byte, 100) + hasher := fnv.New32a() + hasher.Write(randomValue) + hasher.Write(flowBuf[1:4]) + if err := s.SerializeAddrHdr(tmpBuffer); err != nil { + panic(err) + } + hasher.Write(tmpBuffer[:s.AddrHdrLen()]) + return hasher.Sum32() % uint32(numProcs) + } + + // this helper returns the procID by using the extraction + // from dataplane.computeProcID() + computeProcIDHelper := func(payload []byte, s *slayers.SCION) (uint32, error) { + flowIdBuffer := make([]byte, 3) + hasher := fnv.New32a() + buffer := gopacket.NewSerializeBuffer() + err := gopacket.SerializeLayers(buffer, + gopacket.SerializeOptions{FixLengths: true}, + s, gopacket.Payload(payload)) + require.NoError(t, err) + raw := buffer.Bytes() + + return computeProcID(raw, numProcs, randomValue, flowIdBuffer, hasher) + } + type ret struct { + payload []byte + s *slayers.SCION + } + // Each testcase has a function that returns a set of ret structs where + // all rets of that set are expected to return the same hash value + testCases := map[string]func(t *testing.T) []ret{ + "basic": func(t *testing.T) []ret { + payload := []byte("x") + return []ret{ + { + payload: payload, + s: prepBaseMsg(t, payload, (1<<20)-1), + }, + } + }, + "different payload does not affect hashing": func(t *testing.T) []ret { + rets := make([]ret, 10) + for i := 0; i < 10; i++ { + rets[i].payload = make([]byte, 100) + _, err := rand.Read(rets[i].payload) + spkt := prepBaseMsg(t, rets[i].payload, 1) + assert.NoError(t, err) + rets[i].s = spkt + } + return rets + }, + "flowID is extracted correctly independing of trafficId": func(t *testing.T) []ret { + rets := make([]ret, 16) + payload := make([]byte, 100) + for i := 0; i < 16; i++ { + rets[i].payload = payload + spkt := prepBaseMsg(t, rets[i].payload, 1) + spkt.TrafficClass = uint8(i) + rets[i].s = spkt + } + return rets + }, + "ipv4 to ipv4": func(t *testing.T) []ret { + payload := make([]byte, 100) + spkt := prepBaseMsg(t, payload, 1) + _ = spkt.SetDstAddr(addr.HostIP(netip.AddrFrom4([4]byte{10, 0, 200, 200}))) + _ = spkt.SetSrcAddr(addr.HostIP(netip.AddrFrom4([4]byte{10, 0, 200, 200}))) + assert.Equal(t, slayers.T4Ip, spkt.DstAddrType) + assert.Equal(t, slayers.T4Ip, spkt.SrcAddrType) + return []ret{ + { + payload: payload, + s: spkt, + }, + } + }, + "ipv6 to ipv4": func(t *testing.T) []ret { + payload := make([]byte, 100) + spkt := prepBaseMsg(t, payload, 1) + _ = spkt.SetDstAddr(addr.HostIP(netip.AddrFrom4([4]byte{10, 0, 200, 200}))) + _ = spkt.SetSrcAddr(addr.HostIP(netip.MustParseAddr("2001:db8::68"))) + assert.Equal(t, slayers.T4Ip, spkt.DstAddrType) + assert.Equal(t, slayers.T16Ip, int(spkt.SrcAddrType)) + return []ret{ + { + payload: payload, + s: spkt, + }, + } + }, + "svc to ipv4": func(t *testing.T) []ret { + payload := make([]byte, 100) + spkt := prepBaseMsg(t, payload, 1) + spkt.DstAddrType = slayers.T4Ip + _ = spkt.SetDstAddr(addr.HostIP(netip.AddrFrom4([4]byte{10, 0, 200, 200}))) + _ = spkt.SetSrcAddr(addr.HostSVC(addr.SvcWildcard)) + assert.Equal(t, slayers.T4Ip, spkt.DstAddrType) + assert.Equal(t, slayers.T4Svc, int(spkt.SrcAddrType)) + return []ret{ + { + payload: payload, + s: spkt, + }, + } + }, + } + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + rets := tc(t) + if len(rets) == 0 { + return + } + expected := referenceHash(rets[0].s) + for _, r := range rets { + actual, err := computeProcIDHelper(r.payload, r.s) + // this tests do not test errors, hence no errors should occur + assert.NoError(t, err) + assert.Equal(t, expected, actual) + } + }) + } +} + +func TestComputeProcIdErrorCases(t *testing.T) { + type test struct { + data []byte + expectedError error + } + testCases := map[string]test{ + "packet shorter than common header len": { + data: make([]byte, 10), + expectedError: serrors.New("Packet is too short"), + }, + "packet len = CmnHdrLen + addrHdrLen": { + data: []byte{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + }, + expectedError: nil, + }, + "packet len < CmnHdrLen + addrHdrLen": { + data: []byte{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + }, + expectedError: serrors.New("Packet is too short"), + }, + "packet len = CmnHdrLen + addrHdrLen (16IP)": { + data: []byte{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x33, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + }, + expectedError: nil, + }, + "packet len < CmnHdrLen + addrHdrLen (16IP)": { + data: []byte{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x33, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + }, + expectedError: serrors.New("Packet is too short"), + }, + } + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + randomValue := []byte{1, 2, 3, 4} + flowIdBuffer := make([]byte, 3) + _, actualErr := computeProcID(tc.data, 10000, randomValue, flowIdBuffer, fnv.New32a()) + if tc.expectedError != nil { + assert.Equal(t, tc.expectedError.Error(), actualErr.Error()) + } else { + assert.NoError(t, actualErr) + } + }) + } +} + +func serializedBaseMsg(t *testing.T, payload []byte, flowId uint32) []byte { + s := prepBaseMsg(t, payload, flowId) + buffer := gopacket.NewSerializeBuffer() + err := gopacket.SerializeLayers(buffer, + gopacket.SerializeOptions{FixLengths: true}, + s, gopacket.Payload(payload)) + assert.NoError(t, err) + return buffer.Bytes() +} + +func prepBaseMsg(t *testing.T, payload []byte, flowId uint32) *slayers.SCION { + spkt := &slayers.SCION{ + Version: 0, + TrafficClass: 0xb8, + FlowID: flowId, + NextHdr: slayers.L4UDP, + PathType: scion.PathType, + DstIA: xtest.MustParseIA("1-ff00:0:110"), + SrcIA: xtest.MustParseIA("1-ff00:0:111"), + Path: &scion.Raw{}, + PayloadLen: 18, + } + + dpath := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 1, + SegLen: [3]uint8{3, 0, 0}, + }, + NumINF: 1, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + {SegID: 0x111, ConsDir: true, Timestamp: util.TimeToSecs(time.Now())}, + }, + + HopFields: []path.HopField{ + {ConsIngress: 41, ConsEgress: 40}, + {ConsIngress: 31, ConsEgress: 30}, + {ConsIngress: 1, ConsEgress: 0}, + }, + } + spkt.Path = dpath + return spkt +} diff --git a/router/dataplane_test.go b/router/dataplane_test.go index effd7199c..1eb6b6d1d 100644 --- a/router/dataplane_test.go +++ b/router/dataplane_test.go @@ -1,4 +1,5 @@ // Copyright 2020 Anapaya Systems +// Copyright 2023 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,7 +22,6 @@ import ( "net" "net/netip" "sync" - "syscall" "testing" "time" @@ -50,6 +50,8 @@ import ( "github.com/scionproto/scion/router/mock_router" ) +var metrics = router.GetMetrics() + func TestDataPlaneAddInternalInterface(t *testing.T) { internalIP := net.ParseIP("198.51.100.1") t.Run("fails after serve", func(t *testing.T) { @@ -189,15 +191,12 @@ func TestDataPlaneRun(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - metrics := router.NewMetrics() - testCases := map[string]struct { prepareDP func(*gomock.Controller, chan<- struct{}) *router.DataPlane }{ "route 10 msg from external to internal": { prepareDP: func(ctrl *gomock.Controller, done chan<- struct{}) *router.DataPlane { ret := &router.DataPlane{Metrics: metrics} - key := []byte("testkey_xxxxxxxx") local := xtest.MustParseIA("1-ff00:0:110") @@ -205,22 +204,24 @@ func TestDataPlaneRun(t *testing.T) { mInternal := mock_router.NewMockBatchConn(ctrl) mInternal.EXPECT().ReadBatch(gomock.Any()).Return(0, nil).AnyTimes() - matchFlags := gomock.Eq(syscall.MSG_DONTWAIT) - for i := 0; i < 10; i++ { - ii := i - mInternal.EXPECT().WriteBatch(gomock.Any(), matchFlags).DoAndReturn( - func(ms underlayconn.Messages, flags int) (int, error) { - want := bytes.Repeat([]byte("actualpayloadbytes"), ii) - if len(ms[0].Buffers[0]) != len(want)+84 { + mInternal.EXPECT().WriteBatch(gomock.Any(), 0).DoAndReturn( + func(ms underlayconn.Messages, flags int) (int, error) { + if totalCount == 0 { + t.Fail() + return 0, nil + } + for _, msg := range ms { + want := bytes.Repeat([]byte("actualpayloadbytes"), 10-totalCount) + if len(msg.Buffers[0]) != len(want)+84 { return 1, nil } totalCount-- if totalCount == 0 { done <- struct{}{} } - return 1, nil - }) - } + } + return len(ms), nil + }).AnyTimes() _ = ret.AddInternalInterface(mInternal, net.IP{}) mExternal := mock_router.NewMockBatchConn(ctrl) @@ -533,18 +534,21 @@ func TestDataPlaneRun(t *testing.T) { }, }, } - for name, tc := range testCases { name, tc := name, tc t.Run(name, func(t *testing.T) { t.Parallel() + runConfig := &router.RunConfig{ + NumProcessors: 8, + BatchSize: 256, + } ch := make(chan struct{}) dp := tc.prepareDP(ctrl, ch) errors := make(chan error) ctx, cancelF := context.WithCancel(context.Background()) defer cancelF() go func() { - errors <- dp.Run(ctx) + errors <- dp.Run(ctx, runConfig) }() for done := false; !done; { @@ -1176,7 +1180,6 @@ func TestProcessPkt(t *testing.T) { if err != nil { return } - assert.NotNil(t, result.OutConn) outPkt := &ipv4.Message{ Buffers: [][]byte{result.OutPkt}, Addr: result.OutAddr, diff --git a/router/export_test.go b/router/export_test.go index 186bbeede..32d2d14b8 100644 --- a/router/export_test.go +++ b/router/export_test.go @@ -1,4 +1,5 @@ // Copyright 2020 Anapaya Systems +// Copyright 2023 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,6 +25,12 @@ import ( "github.com/scionproto/scion/private/topology" ) +var metrics = NewMetrics() + +func GetMetrics() *Metrics { + return metrics +} + var NewServices = newServices type ProcessResult struct { @@ -64,14 +71,14 @@ func (d *DataPlane) FakeStart() { func (d *DataPlane) ProcessPkt(ifID uint16, m *ipv4.Message) (ProcessResult, error) { - p := newPacketProcessor(d, ifID) + p := newPacketProcessor(d) var srcAddr *net.UDPAddr // for real packets received from ReadBatch this is always non-nil. // Allow nil in test cases for brevity. if m.Addr != nil { srcAddr = m.Addr.(*net.UDPAddr) } - result, err := p.processPkt(m.Buffers[0], srcAddr) + result, err := p.processPkt(m.Buffers[0], srcAddr, ifID) return ProcessResult{processResult: result}, err } diff --git a/router/metrics.go b/router/metrics.go index a9bb86d95..71a09a03c 100644 --- a/router/metrics.go +++ b/router/metrics.go @@ -25,6 +25,7 @@ type Metrics struct { OutputBytesTotal *prometheus.CounterVec InputPacketsTotal *prometheus.CounterVec OutputPacketsTotal *prometheus.CounterVec + ProcessedPackets *prometheus.CounterVec DroppedPacketsTotal *prometheus.CounterVec InterfaceUp *prometheus.GaugeVec BFDInterfaceStateChanges *prometheus.CounterVec @@ -42,6 +43,13 @@ type Metrics struct { // with the default registry. func NewMetrics() *Metrics { return &Metrics{ + ProcessedPackets: promauto.NewCounterVec( + prometheus.CounterOpts{ + Name: "router_processed_pkts_total", + Help: "Total number of packets processed by the processor", + }, + []string{"interface", "isd_as", "neighbor_isd_as"}, + ), InputBytesTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "router_input_bytes_total", @@ -73,10 +81,9 @@ func NewMetrics() *Metrics { DroppedPacketsTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "router_dropped_pkts_total", - Help: "Total number of packets dropped by the router. This metric reports " + - "the number of packets that were dropped because of errors.", + Help: "Total number of packets dropped by the router.", }, - []string{"interface", "isd_as", "neighbor_isd_as"}, + []string{"interface", "isd_as", "neighbor_isd_as", "reason"}, ), InterfaceUp: promauto.NewGaugeVec( prometheus.GaugeOpts{ From 09b5dea553dfea38013e5c0d30750cd3fe003d36 Mon Sep 17 00:00:00 2001 From: Sebastian Leisinger Date: Fri, 21 Jul 2023 16:07:34 +0200 Subject: [PATCH 040/255] python: update pyyaml to 6.0.1 (#4370) Update pyyaml dependency from 6.0.0 -> 6.0.1, as amendment to #4367. The actual issue that had caused our builds to fail suddenly, was not related to the license_file warning, but an AttributeError related to a "cython_sources" option. It appears that pyyaml had an unconstrained version of for Cython as a build system dependency. When Cython 3 was released, this started to fail. Pyyaml 6.0.1 now has a constraint for Cython version < 3, which should keep things working. Somewhat worrying, and not addressed by this change, is the fact that the build system dependencies do not seem to be pinned by our requirements.txt file. --- tools/env/pip3/requirements.in | 2 +- tools/env/pip3/requirements.txt | 82 ++++++++++++++++----------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/tools/env/pip3/requirements.in b/tools/env/pip3/requirements.in index 4cb789098..b49e86c45 100644 --- a/tools/env/pip3/requirements.in +++ b/tools/env/pip3/requirements.in @@ -1,5 +1,5 @@ toml==0.10.2 -pyyaml==6.0.0 +pyyaml==6.0.1 plumbum==1.6.9 supervisor==4.2.1 supervisor-wildcards==0.1.3 diff --git a/tools/env/pip3/requirements.txt b/tools/env/pip3/requirements.txt index f7e050319..15a4b91ba 100644 --- a/tools/env/pip3/requirements.txt +++ b/tools/env/pip3/requirements.txt @@ -8,47 +8,47 @@ plumbum==1.6.9 \ --hash=sha256:16b9e19d96c80f2e9d051ef5f04927b834a6ac0ce5d2768eb8662b5cd53e43df \ --hash=sha256:91418dcc66b58ab9d2e3b04b3d1e0d787dc45923154fb8b4a826bd9316dba0d6 # via -r tools/env/pip3/requirements.in -pyyaml==6.0.0 \ - --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ - --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ - --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ - --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ - --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ - --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ - --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ - --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ - --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ - --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ - --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ - --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ - --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ - --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ - --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ - --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ - --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ - --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ - --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ - --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ - --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ - --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ - --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ - --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ - --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ - --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ - --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ - --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ - --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ - --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ - --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ - --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ - --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ - --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ - --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ - --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ - --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ - --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ - --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ - --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 +pyyaml==6.0.1 \ + --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ + --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ + --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ + --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ + --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ + --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ + --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ + --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ + --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ + --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ + --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ + --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ + --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ + --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ + --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ + --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ + --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ + --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ + --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ + --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ + --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ + --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ + --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ + --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ + --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ + --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ + --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ + --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ + --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ + --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ + --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ + --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ + --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ + --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ + --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ + --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ + --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ + --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ + --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ + --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f # via -r tools/env/pip3/requirements.in six==1.15.0 \ --hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \ From 708bdc2493788a47605d187302380b38a0db73ec Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 27 Jul 2023 16:53:19 +0200 Subject: [PATCH 041/255] repo: drop partial colibri implementation (#4372) A partial implementation of colibri was added in a series of PRs (#3446, ..., #3905). This has not been sufficiently completed to become operational, i.e. the colibri implementation in this repository has effectively remained dead code. The colibri prototype was further developed in a fork, github.com/netsec-ethz/scion, and changes have no longer been upstreamed. Consequently the remaining colibri code here has become stale and keeping this is no longer of great use. --- .golangcilint.yml | 10 +- control/colibri/reservation/BUILD.bazel | 28 - control/colibri/reservation/conf/BUILD.bazel | 23 - .../colibri/reservation/conf/capacities.go | 116 --- .../reservation/conf/capacities_test.go | 208 ----- .../reservation/conf/testdata/caps1.json | 26 - .../reservation/conf/testdata/caps2.json | 7 - control/colibri/reservation/e2e/BUILD.bazel | 37 - control/colibri/reservation/e2e/index.go | 44 - control/colibri/reservation/e2e/request.go | 194 ----- .../colibri/reservation/e2e/request_test.go | 220 ----- .../colibri/reservation/e2e/reservation.go | 109 --- .../reservation/e2e/reservation_test.go | 133 --- control/colibri/reservation/e2e/response.go | 82 -- control/colibri/reservation/index.go | 122 --- control/colibri/reservation/index_test.go | 196 ----- control/colibri/reservation/request.go | 45 - .../reservation/reservationdbtest/BUILD.bazel | 18 - .../reservationdbtest/reservationdbtest.go | 704 --------------- .../colibri/reservation/segment/BUILD.bazel | 37 - .../reservation/segment/admission/BUILD.bazel | 9 - .../reservation/segment/admission/admitter.go | 28 - .../segment/admission/impl/BUILD.bazel | 33 - .../segment/admission/impl/stateless.go | 292 ------- .../segment/admission/impl/stateless_test.go | 522 ----------- .../reservation/segment/export_test.go | 26 - control/colibri/reservation/segment/index.go | 75 -- control/colibri/reservation/segment/path.go | 159 ---- .../colibri/reservation/segment/path_test.go | 181 ---- .../colibri/reservation/segment/request.go | 92 -- .../reservation/segment/reservation.go | 233 ----- .../reservation/segment/reservation_test.go | 238 ------ .../colibri/reservation/segment/response.go | 101 --- .../reservation/segmenttest/BUILD.bazel | 13 - .../colibri/reservation/segmenttest/common.go | 50 -- .../colibri/reservation/sqlite/BUILD.bazel | 38 - control/colibri/reservation/sqlite/db.go | 809 ------------------ control/colibri/reservation/sqlite/db_test.go | 135 --- control/colibri/reservation/sqlite/schema.go | 103 --- control/colibri/reservation/test/BUILD.bazel | 9 - control/colibri/reservation/test/path.go | 57 -- control/colibri/reservation/types.go | 42 - .../colibri/reservationstorage/BUILD.bazel | 14 - .../reservationstorage/backend/BUILD.bazel | 15 - .../colibri/reservationstorage/backend/db.go | 95 -- .../backend/mock_backend/BUILD.bazel | 28 - .../backend/mock_backend/mock.go | 498 ----------- control/colibri/reservationstorage/store.go | 51 -- control/colibri/reservationstore/BUILD.bazel | 25 - control/colibri/reservationstore/store.go | 594 ------------- .../colibri/reservationstore/store_test.go | 26 - doc/dev/design/ColibriService.md | 11 +- doc/dev/design/index.rst | 2 +- nogo.json | 1 - .../colibri/reservation/BUILD.bazel | 23 - pkg/experimental/colibri/reservation/types.go | 584 ------------- .../colibri/reservation/types_test.go | 515 ----------- tools/topogen.py | 2 - tools/topology/common.py | 2 - tools/topology/config.py | 1 - tools/topology/go.py | 95 -- tools/topology/prometheus.py | 1 - tools/topology/topo.py | 7 - 63 files changed, 13 insertions(+), 8181 deletions(-) delete mode 100644 control/colibri/reservation/BUILD.bazel delete mode 100644 control/colibri/reservation/conf/BUILD.bazel delete mode 100644 control/colibri/reservation/conf/capacities.go delete mode 100644 control/colibri/reservation/conf/capacities_test.go delete mode 100644 control/colibri/reservation/conf/testdata/caps1.json delete mode 100644 control/colibri/reservation/conf/testdata/caps2.json delete mode 100644 control/colibri/reservation/e2e/BUILD.bazel delete mode 100644 control/colibri/reservation/e2e/index.go delete mode 100644 control/colibri/reservation/e2e/request.go delete mode 100644 control/colibri/reservation/e2e/request_test.go delete mode 100644 control/colibri/reservation/e2e/reservation.go delete mode 100644 control/colibri/reservation/e2e/reservation_test.go delete mode 100644 control/colibri/reservation/e2e/response.go delete mode 100644 control/colibri/reservation/index.go delete mode 100644 control/colibri/reservation/index_test.go delete mode 100644 control/colibri/reservation/request.go delete mode 100644 control/colibri/reservation/reservationdbtest/BUILD.bazel delete mode 100644 control/colibri/reservation/reservationdbtest/reservationdbtest.go delete mode 100644 control/colibri/reservation/segment/BUILD.bazel delete mode 100644 control/colibri/reservation/segment/admission/BUILD.bazel delete mode 100644 control/colibri/reservation/segment/admission/admitter.go delete mode 100644 control/colibri/reservation/segment/admission/impl/BUILD.bazel delete mode 100644 control/colibri/reservation/segment/admission/impl/stateless.go delete mode 100644 control/colibri/reservation/segment/admission/impl/stateless_test.go delete mode 100644 control/colibri/reservation/segment/export_test.go delete mode 100644 control/colibri/reservation/segment/index.go delete mode 100644 control/colibri/reservation/segment/path.go delete mode 100644 control/colibri/reservation/segment/path_test.go delete mode 100644 control/colibri/reservation/segment/request.go delete mode 100644 control/colibri/reservation/segment/reservation.go delete mode 100644 control/colibri/reservation/segment/reservation_test.go delete mode 100644 control/colibri/reservation/segment/response.go delete mode 100644 control/colibri/reservation/segmenttest/BUILD.bazel delete mode 100644 control/colibri/reservation/segmenttest/common.go delete mode 100644 control/colibri/reservation/sqlite/BUILD.bazel delete mode 100644 control/colibri/reservation/sqlite/db.go delete mode 100644 control/colibri/reservation/sqlite/db_test.go delete mode 100644 control/colibri/reservation/sqlite/schema.go delete mode 100644 control/colibri/reservation/test/BUILD.bazel delete mode 100644 control/colibri/reservation/test/path.go delete mode 100644 control/colibri/reservation/types.go delete mode 100644 control/colibri/reservationstorage/BUILD.bazel delete mode 100644 control/colibri/reservationstorage/backend/BUILD.bazel delete mode 100644 control/colibri/reservationstorage/backend/db.go delete mode 100644 control/colibri/reservationstorage/backend/mock_backend/BUILD.bazel delete mode 100644 control/colibri/reservationstorage/backend/mock_backend/mock.go delete mode 100644 control/colibri/reservationstorage/store.go delete mode 100644 control/colibri/reservationstore/BUILD.bazel delete mode 100644 control/colibri/reservationstore/store.go delete mode 100644 control/colibri/reservationstore/store_test.go delete mode 100644 pkg/experimental/colibri/reservation/BUILD.bazel delete mode 100644 pkg/experimental/colibri/reservation/types.go delete mode 100644 pkg/experimental/colibri/reservation/types_test.go diff --git a/.golangcilint.yml b/.golangcilint.yml index 3bbbf5eaa..1b79a3240 100644 --- a/.golangcilint.yml +++ b/.golangcilint.yml @@ -73,14 +73,8 @@ issues: - path: pkg/scrypto/cms linters: [goheader] - # Exceptions to errcheck for some experimental colibri code and some old-ish convey tests. + # Exceptions to errcheck for some old-ish convey tests. - linters: [errcheck] - path: "^control/colibri/reservation/e2e/reservation_test.go$|\ - ^control/colibri/reservation/index_test.go$|\ - ^control/colibri/reservation/reservationdbtest/reservationdbtest.go$|\ - ^control/colibri/reservation/segment/reservation_test.go$|\ - ^control/colibri/reservation/sqlite/db_test.go$|\ - ^control/colibri/reservationstore/store.go$|\ - ^pkg/sock/reliable/reconnect/conn_io_test.go$|\ + path: "^pkg/sock/reliable/reconnect/conn_io_test.go$|\ ^pkg/sock/reliable/reconnect/network_test.go$|\ ^pkg/sock/reliable/reconnect/reconnecter_test.go$" diff --git a/control/colibri/reservation/BUILD.bazel b/control/colibri/reservation/BUILD.bazel deleted file mode 100644 index e4da7ae3e..000000000 --- a/control/colibri/reservation/BUILD.bazel +++ /dev/null @@ -1,28 +0,0 @@ -load("//tools/lint:go.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "index.go", - "request.go", - "types.go", - ], - importpath = "github.com/scionproto/scion/control/colibri/reservation", - visibility = ["//visibility:public"], - deps = [ - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/serrors:go_default_library", - "//pkg/private/util:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["index_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/util:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) diff --git a/control/colibri/reservation/conf/BUILD.bazel b/control/colibri/reservation/conf/BUILD.bazel deleted file mode 100644 index ff2704e92..000000000 --- a/control/colibri/reservation/conf/BUILD.bazel +++ /dev/null @@ -1,23 +0,0 @@ -load("//tools/lint:go.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["capacities.go"], - importpath = "github.com/scionproto/scion/control/colibri/reservation/conf", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation:go_default_library", - "//pkg/private/serrors:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["capacities_test.go"], - data = glob(["testdata/**"]), - embed = [":go_default_library"], - deps = [ - "//pkg/private/xtest:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) diff --git a/control/colibri/reservation/conf/capacities.go b/control/colibri/reservation/conf/capacities.go deleted file mode 100644 index d057a31db..000000000 --- a/control/colibri/reservation/conf/capacities.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2020 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 ( - "encoding/json" - "sort" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" -) - -// internal structure used to serialize to and from json. -type capacities struct { - // ingress capacities - CapIn map[uint16]uint64 `json:"ingress_kbps"` - // egress capacities - CapEg map[uint16]uint64 `json:"egress_kbps"` - // configured allowed transit - In2Eg map[uint16]map[uint16]uint64 `json:"ingress_to_egress_kbps"` -} - -// Capacities aka capacity matrix. -type Capacities struct { - c capacities - // derived fields from the above ones: - inIfs []uint16 - egIfs []uint16 -} - -var _ base.Capacities = (*Capacities)(nil) -var _ json.Unmarshaler = (*Capacities)(nil) -var _ json.Marshaler = (*Capacities)(nil) - -func (c *Capacities) IngressInterfaces() []uint16 { return c.inIfs } -func (c *Capacities) EgressInterfaces() []uint16 { return c.egIfs } -func (c *Capacities) Capacity(from, to uint16) uint64 { return c.c.In2Eg[from][to] } -func (c *Capacities) CapacityIngress(ingress uint16) uint64 { return c.c.CapIn[ingress] } -func (c *Capacities) CapacityEgress(egress uint16) uint64 { return c.c.CapEg[egress] } - -// UnmarshalJSON deserializes into the json-aware internal data structure. -func (c *Capacities) UnmarshalJSON(b []byte) error { - if err := json.Unmarshal(b, &c.c); err != nil { - return err - } - return c.init() -} - -// MarshalJSON serializes the internal json-friendly structure. -func (c Capacities) MarshalJSON() ([]byte, error) { - return json.Marshal(c.c) -} - -func (c *Capacities) init() error { - totalEgress := make(map[uint16]uint64) - for ingress, intoMap := range c.c.In2Eg { - var accumIngress uint64 - for egress, cap := range intoMap { - accumIngress += cap - totalEgress[egress] += cap - if egress == ingress && cap != 0 { - return serrors.New("capacity is inconsistent, ingress to itself not zero", - "ingress", ingress) - } - } - if _, found := c.c.CapIn[ingress]; !found { - return serrors.New("capacity is inconsistent, must declare ingress capacity", - "ingress", ingress) - } - if accumIngress > c.c.CapIn[ingress] { - return serrors.New("capacity is inconsistent, ingress accum too high", "ingress", - ingress, "ingress_accum", accumIngress, "ingress_declared", c.c.CapIn[ingress]) - } - } - for egress, accum := range totalEgress { - if _, found := c.c.CapEg[egress]; !found { - return serrors.New("capacity is inconsistent, must declare egress capacity", - "egress", egress) - } - if accum > c.c.CapEg[egress] { - return serrors.New("capacity is inconsistent, egress accum too high", "egress", egress, - "egress_accum", accum, "egress_declared", c.c.CapEg[egress]) - } - } - // init list of ingress interfaces - c.inIfs = make([]uint16, len(c.c.CapIn)) - i := 0 - for ifid := range c.c.CapIn { - c.inIfs[i] = ifid - i++ - } - // init list of egress interfaces - c.egIfs = make([]uint16, len(c.c.CapEg)) - i = 0 - for ifid := range c.c.CapEg { - c.egIfs[i] = ifid - i++ - } - // sort them just to simplify debugging - sort.Slice(c.inIfs, func(i, j int) bool { return c.inIfs[i] < c.inIfs[j] }) - sort.Slice(c.egIfs, func(i, j int) bool { return c.egIfs[i] < c.egIfs[j] }) - - return nil -} diff --git a/control/colibri/reservation/conf/capacities_test.go b/control/colibri/reservation/conf/capacities_test.go deleted file mode 100644 index 481861976..000000000 --- a/control/colibri/reservation/conf/capacities_test.go +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2020 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 ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/pkg/private/xtest" -) - -func TestJson(t *testing.T) { - // test that this number cannot be represented with float64 - // (it will be used in one of the test cases) - var bigint uint64 = 4418489049307132905 - require.NotEqual(t, bigint, uint64(float64(bigint))) - - cases := map[string]struct { - filename string - cap Capacities - }{ - "using all keys": { - filename: "caps1.json", - cap: Capacities{c: capacities{ - CapIn: map[uint16]uint64{1: 100, 2: 200, 3: 300}, - CapEg: map[uint16]uint64{1: 100, 2: 200, 3: 40}, - In2Eg: map[uint16]map[uint16]uint64{ - 1: {2: 10, 3: 20}, - 2: {1: 10, 3: 20}, - 3: {1: 10, 2: 20}, - }, - }, - }, - }, - "big num no float": { - filename: "caps2.json", - cap: Capacities{c: capacities{ - CapIn: map[uint16]uint64{1: bigint}, - }, - }, - }, - } - - for name, tc := range cases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - require.NoError(t, tc.cap.init()) - buf, err := json.MarshalIndent(tc.cap, "", " ") - buf = append(buf, '\n') - require.NoError(t, err) - expectedJSON := xtest.MustReadFromFile(t, tc.filename) - require.Equal(t, expectedJSON, buf) - c2 := Capacities{} - err = c2.UnmarshalJSON(expectedJSON) - require.NoError(t, err) - require.Equal(t, tc.cap, c2) - }) - } -} - -func TestValidation(t *testing.T) { - cases := map[string]struct { - okay bool - cap Capacities - }{ - "okay": { - okay: true, - cap: Capacities{c: capacities{ - CapIn: map[uint16]uint64{1: 100, 2: 200, 3: 300}, - CapEg: map[uint16]uint64{1: 100, 2: 200, 3: 40}, - In2Eg: map[uint16]map[uint16]uint64{ - 1: {2: 10, 3: 20}, - 2: {1: 10, 3: 20}, - 3: {1: 10, 2: 20}, - }, - }, - }, - }, - "too much ingress": { - okay: false, - cap: Capacities{c: capacities{ - CapIn: map[uint16]uint64{1: 10}, - In2Eg: map[uint16]map[uint16]uint64{ - 1: {2: 10, 3: 1}, - }, - }, - }, - }, - "too much egress": { - okay: false, - cap: Capacities{c: capacities{ - CapIn: map[uint16]uint64{1: 100, 2: 100, 3: 100}, - CapEg: map[uint16]uint64{1: 100, 2: 100, 3: 100}, - In2Eg: map[uint16]map[uint16]uint64{ - 1: {2: 90, 3: 1}, - 3: {2: 20, 1: 1}, - }, - }, - }, - }, - "ingress to itself (reflection not allowed)": { - okay: false, - cap: Capacities{c: capacities{ - CapIn: map[uint16]uint64{1: 100, 2: 100, 3: 100}, - CapEg: map[uint16]uint64{1: 100, 2: 100, 3: 100}, - In2Eg: map[uint16]map[uint16]uint64{ - 1: {1: 10, 3: 1}, - }, - }, - }, - }, - "too few ingress capacities": { - okay: false, - cap: Capacities{c: capacities{ - CapIn: map[uint16]uint64{1: 100, 3: 100}, - CapEg: map[uint16]uint64{1: 100, 2: 100, 3: 100}, - In2Eg: map[uint16]map[uint16]uint64{ - 1: {2: 0, 3: 0}, - 2: {1: 0, 3: 0}, - 3: {1: 0, 2: 0}, - }, - }, - }, - }, - "too few egress capacities": { - okay: false, - cap: Capacities{c: capacities{ - CapIn: map[uint16]uint64{1: 100, 2: 100, 3: 100}, - CapEg: map[uint16]uint64{1: 100, 3: 100}, - In2Eg: map[uint16]map[uint16]uint64{ - 1: {2: 0, 3: 0}, - 2: {1: 0, 3: 0}, - 3: {1: 0, 2: 0}, - }, - }, - }, - }, - } - - for name, tc := range cases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - err := tc.cap.init() - if tc.okay { - require.NoError(t, err) - } else { - require.Error(t, err) - } - }) - } -} - -func TestCapacities(t *testing.T) { - c := &Capacities{c: capacities{ - CapIn: map[uint16]uint64{1: 100, 2: 100, 3: 100}, - CapEg: map[uint16]uint64{1: 100, 2: 100, 3: 100}, - In2Eg: map[uint16]map[uint16]uint64{ - 1: {2: 12, 3: 13}, - 2: {1: 21, 3: 23}, - 3: {1: 31, 2: 32}, - }, - }, - } - copy := cloneCapacities(c) // save a copy of the original - require.Equal(t, uint64(100), c.CapacityIngress(1)) - require.Equal(t, uint64(0), c.CapacityIngress(5)) - - require.Equal(t, copy, c) -} - -func cloneCapacities(c *Capacities) *Capacities { - ret := &Capacities{} - copy(ret.inIfs, c.inIfs) - copy(ret.egIfs, c.egIfs) - ret.c.CapIn = make(map[uint16]uint64) - for k, v := range c.c.CapIn { - ret.c.CapIn[k] = v - } - ret.c.CapEg = make(map[uint16]uint64) - for k, v := range c.c.CapEg { - ret.c.CapEg[k] = v - } - ret.c.In2Eg = make(map[uint16]map[uint16]uint64) - for k, v := range c.c.In2Eg { - m := make(map[uint16]uint64) - for k, v := range v { - m[k] = v - } - ret.c.In2Eg[k] = m - } - return ret -} diff --git a/control/colibri/reservation/conf/testdata/caps1.json b/control/colibri/reservation/conf/testdata/caps1.json deleted file mode 100644 index 0fc0bdcf6..000000000 --- a/control/colibri/reservation/conf/testdata/caps1.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "ingress_kbps": { - "1": 100, - "2": 200, - "3": 300 - }, - "egress_kbps": { - "1": 100, - "2": 200, - "3": 40 - }, - "ingress_to_egress_kbps": { - "1": { - "2": 10, - "3": 20 - }, - "2": { - "1": 10, - "3": 20 - }, - "3": { - "1": 10, - "2": 20 - } - } -} diff --git a/control/colibri/reservation/conf/testdata/caps2.json b/control/colibri/reservation/conf/testdata/caps2.json deleted file mode 100644 index a4ec915fd..000000000 --- a/control/colibri/reservation/conf/testdata/caps2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ingress_kbps": { - "1": 4418489049307132905 - }, - "egress_kbps": null, - "ingress_to_egress_kbps": null -} diff --git a/control/colibri/reservation/e2e/BUILD.bazel b/control/colibri/reservation/e2e/BUILD.bazel deleted file mode 100644 index c56f5fb09..000000000 --- a/control/colibri/reservation/e2e/BUILD.bazel +++ /dev/null @@ -1,37 +0,0 @@ -load("//tools/lint:go.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "index.go", - "request.go", - "reservation.go", - "response.go", - ], - importpath = "github.com/scionproto/scion/control/colibri/reservation/e2e", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation:go_default_library", - "//control/colibri/reservation/segment:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/serrors:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "request_test.go", - "reservation_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//control/colibri/reservation/segment:go_default_library", - "//control/colibri/reservation/segmenttest:go_default_library", - "//control/colibri/reservation/test:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/util:go_default_library", - "//pkg/private/xtest:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) diff --git a/control/colibri/reservation/e2e/index.go b/control/colibri/reservation/e2e/index.go deleted file mode 100644 index f704ce6b1..000000000 --- a/control/colibri/reservation/e2e/index.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 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 e2e - -import ( - "time" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" -) - -// Index represents an E2E index. These are interpreted as "active", so the reservation initiator -// must cleanup indices along the path when the setup didn't finish correctly. -type Index struct { - Idx reservation.IndexNumber - Expiration time.Time - AllocBW reservation.BWCls // also present in the token - Token *reservation.Token -} - -type Indices []Index - -var _ base.IndicesInterface = (*Indices)(nil) - -func (idxs Indices) Len() int { return len(idxs) } -func (idxs Indices) GetIndexNumber(i int) reservation.IndexNumber { return idxs[i].Idx } -func (idxs Indices) GetExpiration(i int) time.Time { return idxs[i].Expiration } -func (idxs Indices) GetAllocBW(i int) reservation.BWCls { return idxs[i].AllocBW } -func (idxs Indices) GetToken(i int) *reservation.Token { return idxs[i].Token } -func (idxs Indices) Rotate(i int) base.IndicesInterface { - return append(idxs[i:], idxs[:i]...) -} diff --git a/control/colibri/reservation/e2e/request.go b/control/colibri/reservation/e2e/request.go deleted file mode 100644 index a8fb84754..000000000 --- a/control/colibri/reservation/e2e/request.go +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2020 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 e2e - -import ( - "time" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" -) - -// Request is the base struct for any type of COLIBRI e2e request. -type Request struct { - base.RequestMetadata // information about the request (forwarding path) - ID reservation.E2EID // the ID this request refers to - Index reservation.IndexNumber // the index this request refers to - Timestamp time.Time // the mandatory timestamp -} - -// NewRequest constructs the e2e Request type. -func NewRequest(ts time.Time, id *reservation.E2EID, idx reservation.IndexNumber, - path base.ColibriPath) (*Request, error) { - - metadata, err := base.NewRequestMetadata(path) - if err != nil { - return nil, serrors.WrapStr("new segment request", err) - } - - if id == nil { - return nil, serrors.New("new e2e request with nil ID") - } - - return &Request{ - RequestMetadata: *metadata, - ID: *id, - Index: idx, - Timestamp: ts, - }, nil -} - -// SetupRequest represents all possible e2e setup requests. -type SetupRequest interface { - IsSuccessful() bool - GetCommonSetupReq() *SetupReq // return the underlying basic SetupReq (common for all) -} - -// SetupReq is an e2e setup/renewal request, that has been so far accepted. -type SetupReq struct { - Request - SegmentRsvs []reservation.SegmentID - SegmentRsvASCount []uint8 // how many ASes per segment reservation - RequestedBW reservation.BWCls - AllocationTrail []reservation.BWCls - totalASCount int - currentASSegmentRsvIndex int // the index in SegmentRsv for the current AS - isTransfer bool -} - -// NewSetupRequest creates and initializes an e2e setup request common for both success and failure. -func NewSetupRequest(r *Request, segRsvs []reservation.SegmentID, segRsvCount []uint8, - requestedBW reservation.BWCls, allocTrail []reservation.BWCls) (*SetupReq, error) { - - if len(segRsvs) != len(segRsvCount) || len(segRsvs) == 0 { - return nil, serrors.New("e2e setup request invalid", "seg_rsv_len", len(segRsvs), - "seg_rsv_count_len", len(segRsvCount)) - } - totalASCount := 0 - currASindex := -1 - isTransfer := false - n := len(allocTrail) - 1 - for i, c := range segRsvCount { - totalASCount += int(c) - n -= int(c) - 1 - if i == len(segRsvCount)-1 { - n-- // the last segment spans 1 more AS - } - if n < 0 && currASindex < 0 { - currASindex = i - isTransfer = i < len(segRsvCount)-1 && n == -1 // dst AS is no transfer - } - } - totalASCount -= len(segRsvCount) - 1 - if currASindex < 0 { - return nil, serrors.New("error initializing e2e request", - "alloc_trail_len", len(allocTrail), "seg_rsv_count", segRsvCount) - } - return &SetupReq{ - Request: *r, - SegmentRsvs: segRsvs, - SegmentRsvASCount: segRsvCount, - RequestedBW: requestedBW, - AllocationTrail: allocTrail, - totalASCount: totalASCount, - currentASSegmentRsvIndex: currASindex, - isTransfer: isTransfer, - }, nil -} - -// GetCommonSetupReq returns the pointer to the data structure. -func (r *SetupReq) GetCommonSetupReq() *SetupReq { - return r -} - -func (r *SetupReq) Transfer() bool { - return r.isTransfer -} - -type PathLocation int - -const ( - Source PathLocation = iota - Transit - Destination -) - -func (l PathLocation) String() string { - switch l { - case Source: - return "source" - case Transit: - return "trantit" - case Destination: - return "destination" - } - return "unknown path location" -} - -// Location returns the location of this node in the path of the request. -func (r *SetupReq) Location() PathLocation { - switch len(r.AllocationTrail) { - case 0: - return Source - case r.totalASCount: - return Destination - default: - return Transit - } -} - -// SegmentRsvIDsForThisAS returns the segment reservation ID this AS belongs to. Iff this -// AS is a transfer AS (stitching point), there will be two reservation IDs returned, in the -// order of traversal. -func (r *SetupReq) SegmentRsvIDsForThisAS() []reservation.SegmentID { - indices := make([]reservation.SegmentID, 1, 2) - indices[0] = r.SegmentRsvs[r.currentASSegmentRsvIndex] - if r.isTransfer { - indices = append(indices, r.SegmentRsvs[r.currentASSegmentRsvIndex+1]) - } - return indices -} - -// SetupReqSuccess is a successful e2e setup request traveling along the reservation path. -type SetupReqSuccess struct { - SetupReq - Token reservation.Token -} - -var _ SetupRequest = (*SetupReqSuccess)(nil) - -// IsSuccessful returns true. -func (s *SetupReqSuccess) IsSuccessful() bool { - return true -} - -// SetupReqFailure is a failed e2e setup request also traveling along the reservation path. -type SetupReqFailure struct { - SetupReq - ErrorCode uint8 -} - -var _ SetupRequest = (*SetupReqFailure)(nil) - -// IsSuccessful returns false, as this is a failed setup. -func (s *SetupReqFailure) IsSuccessful() bool { - return false -} - -// CleanupReq is a cleaup request for an e2e index. -type CleanupReq struct { - Request -} diff --git a/control/colibri/reservation/e2e/request_test.go b/control/colibri/reservation/e2e/request_test.go deleted file mode 100644 index 25b0150ee..000000000 --- a/control/colibri/reservation/e2e/request_test.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2020 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 e2e - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/control/colibri/reservation/test" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/util" - "github.com/scionproto/scion/pkg/private/xtest" -) - -func TestNewRequest(t *testing.T) { - _, err := NewRequest(util.SecsToTime(1), nil, 1, nil) - require.Error(t, err) - _, err = NewRequest(util.SecsToTime(1), nil, 1, test.NewTestPath()) - require.Error(t, err) - id, err := reservation.NewE2EID(xtest.MustParseAS("ff00:0:111"), - xtest.MustParseHexString("beefcafebeefcafebeef")) - require.NoError(t, err) - r, err := NewRequest(util.SecsToTime(1), id, 1, test.NewTestPath()) - require.NoError(t, err) - require.Equal(t, util.SecsToTime(1), r.Timestamp) - require.Equal(t, id, &r.ID) - require.Equal(t, reservation.IndexNumber(1), r.Index) - require.Equal(t, test.NewTestPath(), r.RequestMetadata.Path()) -} - -func TestNewSetupRequest(t *testing.T) { - _, err := NewSetupRequest(nil, nil, nil, 5, nil) - require.Error(t, err) - id, err := reservation.NewE2EID(xtest.MustParseAS("ff00:0:111"), - xtest.MustParseHexString("beefcafebeefcafebeef")) - require.NoError(t, err) - path := test.NewTestPath() - baseReq, err := NewRequest(util.SecsToTime(1), id, 1, path) - require.NoError(t, err) - _, err = NewSetupRequest(baseReq, nil, nil, 5, nil) - require.Error(t, err) - - segmentRsvs := make([]reservation.SegmentID, 0) - _, err = NewSetupRequest(baseReq, segmentRsvs, nil, 5, nil) - require.Error(t, err) - segmentASCount := make([]uint8, 0) - _, err = NewSetupRequest(baseReq, segmentRsvs, segmentASCount, 5, nil) - require.Error(t, err) - trail := make([]reservation.BWCls, 0) - _, err = NewSetupRequest(baseReq, segmentRsvs, segmentASCount, 5, trail) - require.Error(t, err) - - cases := map[string]struct { - ASCountPerSegment []uint8 - TrailLength int - TotalASCount int - SegmentIndex int - PathLocation PathLocation - IsTransfer bool - }{ - // "3-2-4 at 0" means: - // 3 segments, with 3 ASes in the first one, 2 and 4 in the others. Trail has 0 components - "2 at 0": { - ASCountPerSegment: []uint8{2}, - TrailLength: 0, - TotalASCount: 2, - SegmentIndex: 0, - PathLocation: Source, - IsTransfer: false, - }, - "2 at 1": { - ASCountPerSegment: []uint8{2}, - TrailLength: 1, - TotalASCount: 2, - SegmentIndex: 0, - PathLocation: Transit, - IsTransfer: false, - }, - "2 at 2": { - ASCountPerSegment: []uint8{2}, - TrailLength: 2, - TotalASCount: 2, - SegmentIndex: 0, - PathLocation: Destination, - IsTransfer: false, - }, - "3-4-5 at 0": { - ASCountPerSegment: []uint8{3, 4, 5}, - TrailLength: 0, - TotalASCount: 10, - SegmentIndex: 0, - PathLocation: Source, - IsTransfer: false, - }, - "3-4-5 at 1": { - ASCountPerSegment: []uint8{3, 4, 5}, - TrailLength: 1, - TotalASCount: 10, - SegmentIndex: 0, - PathLocation: Transit, - IsTransfer: false, - }, - "3-4-5 at 2": { - ASCountPerSegment: []uint8{3, 4, 5}, - TrailLength: 2, - TotalASCount: 10, - SegmentIndex: 0, - PathLocation: Transit, - IsTransfer: true, - }, - "3-4-5 at 3": { - ASCountPerSegment: []uint8{3, 4, 5}, - TrailLength: 3, - TotalASCount: 10, - SegmentIndex: 1, - PathLocation: Transit, - IsTransfer: false, - }, - "3-4-5 at 5": { - ASCountPerSegment: []uint8{3, 4, 5}, - TrailLength: 5, - TotalASCount: 10, - SegmentIndex: 1, - PathLocation: Transit, - IsTransfer: true, - }, - "3-4-5 at 6": { - ASCountPerSegment: []uint8{3, 4, 5}, - TrailLength: 6, - TotalASCount: 10, - SegmentIndex: 2, - PathLocation: Transit, - IsTransfer: false, - }, - "3-4-5 at 9": { - ASCountPerSegment: []uint8{3, 4, 5}, - TrailLength: 9, - TotalASCount: 10, - SegmentIndex: 2, - PathLocation: Transit, - IsTransfer: false, - }, - "3-4-5 at 10": { - ASCountPerSegment: []uint8{3, 4, 5}, - TrailLength: 10, - TotalASCount: 10, - SegmentIndex: 2, - PathLocation: Destination, - IsTransfer: false, - }, - } - for name, tc := range cases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - segmentRsvs := make([]reservation.SegmentID, len(tc.ASCountPerSegment)) - for i := range segmentRsvs { - segmentRsvs[i] = *newTestSegmentID(t) - } - trail := make([]reservation.BWCls, tc.TrailLength) - for i := range trail { - trail[i] = 5 - } - r, err := NewSetupRequest(baseReq, segmentRsvs, tc.ASCountPerSegment, 5, trail) - require.NoError(t, err) - require.Equal(t, tc.TotalASCount, r.totalASCount) - require.Equal(t, tc.SegmentIndex, r.currentASSegmentRsvIndex) - require.Equal(t, tc.PathLocation, r.Location()) - require.Equal(t, tc.IsTransfer, r.Transfer()) - }) - } -} - -func TestInterface(t *testing.T) { - id, err := reservation.NewE2EID(xtest.MustParseAS("ff00:0:111"), - xtest.MustParseHexString("beefcafebeefcafebeef")) - require.NoError(t, err) - path := test.NewTestPath() - baseReq, err := NewRequest(util.SecsToTime(1), id, 1, path) - require.NoError(t, err) - segmentIDs := []reservation.SegmentID{*newTestSegmentID(t)} - - r, err := NewSetupRequest(baseReq, segmentIDs, []uint8{2}, 5, nil) - require.NoError(t, err) - tok, err := reservation.TokenFromRaw(xtest.MustParseHexString( - "16ebdb4f0d042500003f001002bad1ce003f001002facade")) - require.NoError(t, err) - success := SetupReqSuccess{ - SetupReq: *r, - Token: *tok, - } - require.Equal(t, r, success.GetCommonSetupReq()) - failure := SetupReqFailure{ - SetupReq: *r, - ErrorCode: 6, - } - require.Equal(t, r, failure.GetCommonSetupReq()) -} - -// this fcn is helpful here to add segment reservations in the e2e setup request. -func newTestSegmentID(t *testing.T) *reservation.SegmentID { - t.Helper() - id, err := reservation.NewSegmentID(xtest.MustParseAS("ff00:0:1"), - xtest.MustParseHexString("deadbeef")) - require.NoError(t, err) - return id -} diff --git a/control/colibri/reservation/e2e/reservation.go b/control/colibri/reservation/e2e/reservation.go deleted file mode 100644 index 5d84afd7a..000000000 --- a/control/colibri/reservation/e2e/reservation.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2020 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 e2e - -import ( - "time" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" -) - -// Reservation represents an E2E reservation. -type Reservation struct { - ID reservation.E2EID - SegmentReservations []*segment.Reservation // stitched segment reservations - Indices Indices -} - -// Validate will return an error for invalid values. -// It doesn not check for valid path properties and correct end/start AS ID when stiching. -func (r *Reservation) Validate() error { - if err := base.ValidateIndices(r.Indices); err != nil { - return err - } - if len(r.SegmentReservations) < 1 || len(r.SegmentReservations) > 3 { - return serrors.New("wrong number of segment reservations referenced in E2E reservation", - "number", len(r.SegmentReservations)) - } - for i, rsv := range r.SegmentReservations { - if rsv == nil { - return serrors.New("invalid segment reservation referenced by e2e, is nil", - "slice_index", i) - } - if err := rsv.Validate(); err != nil { - return serrors.New("invalid segment reservation referenced by e2e one", - "slice_index", i, "segment_id", rsv.ID) - } - } - return nil -} - -// NewIndex creates a new index in this reservation. The token needs to be created manually. -func (r *Reservation) NewIndex(expTime time.Time) (reservation.IndexNumber, error) { - idx := reservation.IndexNumber(0) - if len(r.Indices) > 0 { - idx = r.Indices[len(r.Indices)-1].Idx.Add(1) - } - newIndices := make(Indices, len(r.Indices)+1) - copy(newIndices, r.Indices) - newIndices[len(newIndices)-1] = Index{ - Expiration: expTime, - Idx: idx, - } - if err := base.ValidateIndices(newIndices); err != nil { - return 0, err - } - r.Indices = newIndices - return idx, nil -} - -// RemoveIndex removes all indices from the beginning until this one, inclusive. -func (r *Reservation) RemoveIndex(idx reservation.IndexNumber) error { - sliceIndex, err := base.FindIndex(r.Indices, idx) - if err != nil { - return err - } - r.Indices = r.Indices[sliceIndex+1:] - return nil -} - -// Index finds the Index with that IndexNumber and returns a pointer to it. Nil if not found. -func (r *Reservation) Index(idx reservation.IndexNumber) *Index { - sliceIndex, err := base.FindIndex(r.Indices, idx) - if err != nil { - return nil - } - return &r.Indices[sliceIndex] -} - -// AllocResv returns the allocated bandwidth by this reservation using the current active index and -// the previous one. The max of those two values is used because the current active index might -// be rolled back with a cleanup request. The return units is Kbps. -func (r *Reservation) AllocResv() uint64 { - var maxBW reservation.BWCls - switch len(r.Indices) { - case 0: - return 0 - case 1: - maxBW = r.Indices[len(r.Indices)-1].AllocBW - default: - maxBW = reservation.MaxBWCls(r.Indices[len(r.Indices)-1].AllocBW, - r.Indices[len(r.Indices)-2].AllocBW) - } - return maxBW.ToKbps() -} diff --git a/control/colibri/reservation/e2e/reservation_test.go b/control/colibri/reservation/e2e/reservation_test.go deleted file mode 100644 index 7a3a9a20e..000000000 --- a/control/colibri/reservation/e2e/reservation_test.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2020 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 e2e - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/control/colibri/reservation/segmenttest" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/util" - "github.com/scionproto/scion/pkg/private/xtest" -) - -func TestValidate(t *testing.T) { - // alright - r := newReservation() - err := r.Validate() - require.NoError(t, err) - - // no segment reservations - r = newReservation() - r.SegmentReservations = make([]*segment.Reservation, 0) - err = r.Validate() - require.Error(t, err) - - // nil segment reservation - r = newReservation() - r.SegmentReservations[0] = nil - err = r.Validate() - require.Error(t, err) - - // invalid segment reservation - r = newReservation() - r.SegmentReservations[0].Path = segment.ReservationTransparentPath{} - err = r.Validate() - require.Error(t, err) - - // more than 3 segment reservations - r = newReservation() - r.SegmentReservations = []*segment.Reservation{ - newSegmentReservation("1-ff00:0:111", "1-ff00:0:110"), - newSegmentReservation("1-ff00:0:111", "1-ff00:0:110"), - newSegmentReservation("1-ff00:0:111", "1-ff00:0:110"), - newSegmentReservation("1-ff00:0:111", "1-ff00:0:110"), - } - err = r.Validate() - require.Error(t, err) -} - -func TestNewIndex(t *testing.T) { - r := newReservation() - expTime := util.SecsToTime(1) - index, err := r.NewIndex(expTime) - require.NoError(t, err) - require.Len(t, r.Indices, 1) - require.Equal(t, r.Indices[0].Idx, index) - index, err = r.NewIndex(expTime) - require.NoError(t, err) - require.Len(t, r.Indices, 2) - require.Equal(t, r.Indices[1].Idx, index) -} - -func TestRemoveIndex(t *testing.T) { - r := newReservation() - expTime := util.SecsToTime(1) - idx, _ := r.NewIndex(expTime) - err := r.RemoveIndex(idx) - require.NoError(t, err) - require.Len(t, r.Indices, 0) -} - -func TestAllocResv(t *testing.T) { - r := newReservation() - // 1 index - r.NewIndex(util.SecsToTime(1)) - r.Index(0).AllocBW = 5 - require.Equal(t, uint64(64), r.AllocResv()) - // 2 indices - r.NewIndex(util.SecsToTime(2)) - r.Index(1).AllocBW = 3 - require.Equal(t, uint64(64), r.AllocResv()) - // 3 indices - r.NewIndex(util.SecsToTime(2)) - r.Index(2).AllocBW = 3 - require.Equal(t, uint64(32), r.AllocResv()) -} - -func newSegmentReservation(asidPath ...string) *segment.Reservation { - if len(asidPath) < 2 { - panic("at least source and destination in the path") - } - r := segmenttest.NewReservation() - // use the asid to create an ID and a path and use them in the reservation - pathComponents := make([]interface{}, len(asidPath)*3) - for i := range asidPath { - pathComponents[i*3] = i * 2 - pathComponents[i*3+1] = asidPath[i] - pathComponents[i*3+2] = i*2 + 1 - } - pathComponents[len(pathComponents)-1] = 0 - r.Path = segmenttest.NewPathFromComponents(pathComponents...) - return r -} - -func newReservation() *Reservation { - id, err := reservation.NewE2EID(xtest.MustParseAS("ff00:0:111"), - xtest.MustParseHexString("beefcafebeefcafebeef")) - if err != nil { - panic(err) - } - rsv := Reservation{ - ID: *id, - SegmentReservations: []*segment.Reservation{ - newSegmentReservation("1-ff00:0:111", "1-ff00:0:110"), - }, - } - return &rsv -} diff --git a/control/colibri/reservation/e2e/response.go b/control/colibri/reservation/e2e/response.go deleted file mode 100644 index 6d294be86..000000000 --- a/control/colibri/reservation/e2e/response.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2020 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 e2e - -import ( - "time" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" -) - -// Response is the base struct for any type of COLIBRI e2e response. -type Response struct { - base.RequestMetadata // information about the request (forwarding path) - ID reservation.E2EID // the ID this request refers to - Index reservation.IndexNumber // the index this request refers to - Accepted bool // success or failure type of response - FailedHop uint8 // if accepted is false, the AS that failed it -} - -// NewResponse contructs the segment Response type. -func NewResponse(ts time.Time, id *reservation.E2EID, idx reservation.IndexNumber, - path base.ColibriPath, accepted bool, failedHop uint8) (*Response, error) { - - metadata, err := base.NewRequestMetadata(path) - if err != nil { - return nil, serrors.WrapStr("new segment request", err) - } - if id == nil { - return nil, serrors.New("new segment response with nil ID") - } - return &Response{ - RequestMetadata: *metadata, - ID: *id, - Index: idx, - Accepted: accepted, - FailedHop: failedHop, - }, nil -} - -// IsHopByHop returns false, as all the responses travel directly to the source endhost. -func (r *Response) IsHopByHop() bool { - return false -} - -// ResponseSetupSuccess is the response to a success setup. It's sent on the reverse direction. -type ResponseSetupSuccess struct { - Response - Token reservation.Token -} - -// ResponseSetupFailure is the response to a failed setup. It's sent on the reverse direction. -// The failed hop is the length of MaxBWs + 1. -type ResponseSetupFailure struct { - Response - ErrorCode uint8 - MaxBWs []reservation.BWCls // granted by ASes in the path until the failed hop -} - -// ResponseCleanupSuccess is a response to a successful cleanup request. -type ResponseCleanupSuccess struct { - Response -} - -// ResponseCleanupFailure is a failed index cleanup. -type ResponseCleanupFailure struct { - Response - ErrorCode uint8 -} diff --git a/control/colibri/reservation/index.go b/control/colibri/reservation/index.go deleted file mode 100644 index 3cff23cd4..000000000 --- a/control/colibri/reservation/index.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2020 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 reservation - -import ( - "sort" - "time" - - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" - "github.com/scionproto/scion/pkg/private/util" -) - -type IndicesInterface interface { - Len() int - GetIndexNumber(i int) reservation.IndexNumber - GetExpiration(i int) time.Time - GetAllocBW(i int) reservation.BWCls - GetToken(i int) *reservation.Token - Rotate(i int) IndicesInterface -} - -// ValidateIndices checks that the indices follow consecutive index numbers, their expiration -// times are greater or equal, and no more than three indices per expiration time. Also no more -// than 16 indices are allowed. -func ValidateIndices(indices IndicesInterface) error { - lastExpiration := util.SecsToTime(0) - lastIndexNumber := reservation.IndexNumber(0).Sub(1) - if indices.Len() > 0 { - lastIndexNumber = indices.GetIndexNumber(0).Sub(1) - if indices.Len() > 16 { - // with only 4 bits to represent the index number, we cannot have more than 16 indices - return serrors.New("too many indices", "index_count", indices.Len()) - } - } - indicesPerExpTime := 0 - for i := 0; i < indices.Len(); i++ { - if indices.GetExpiration(i).Before(lastExpiration) { - return serrors.New("index expires before than a previous one", - "idx", indices.GetIndexNumber(i), - "expiration", indices.GetExpiration(i), "previous_exp", lastExpiration) - } - if indices.GetExpiration(i).Equal(lastExpiration) { - indicesPerExpTime++ - if indicesPerExpTime > 3 { - return serrors.New("more than three indices per expiration time", - "expiration", indices.GetExpiration(i)) - } - } else { - indicesPerExpTime = 1 - } - if indices.GetIndexNumber(i).Sub(lastIndexNumber) != reservation.IndexNumber(1) { - return serrors.New("non consecutive indices", "prev_index_number", lastIndexNumber, - "index_number", indices.GetIndexNumber(i)) - } - lastExpiration = indices.GetExpiration(i) - lastIndexNumber = indices.GetIndexNumber(i) - token := indices.GetToken(i) - if token != nil { - if token.Idx != lastIndexNumber { - return serrors.New("inconsistent token", "token_index_number", token.Idx, - "expected", lastIndexNumber) - } - if token.ExpirationTick != reservation.TickFromTime(lastExpiration) { - return serrors.New("inconsistent token", "token_expiration_tick", - token.ExpirationTick, "expected", reservation.TickFromTime(lastExpiration)) - } - if token.BWCls != indices.GetAllocBW(i) { - return serrors.New("inconsistent token", "token_bw_class", token.BWCls, - "expected", indices.GetAllocBW(i)) - } - } - } - return nil -} - -// FindIndex returns the slice index for the passed IndexNumber. -func FindIndex(indices IndicesInterface, idx reservation.IndexNumber) (int, error) { - var firstIdx reservation.IndexNumber = 0 - if indices.Len() > 0 { - firstIdx = indices.GetIndexNumber(0) - } - sliceIndex := int(idx.Sub(firstIdx)) - if sliceIndex > indices.Len()-1 { - return 0, serrors.New("index not found in this reservation", "index_number", idx, - "indices length", indices.Len()) - } - return sliceIndex, nil -} - -// SortIndices sorts these Indices according to their index number modulo 16, e.g. [14, 15, 0, 1]. -func SortIndices(idxs IndicesInterface) { - if idxs.Len() < 2 { - return - } - sort.Slice(idxs, func(i, j int) bool { - ae, be := idxs.GetExpiration(i), idxs.GetExpiration(j) - ai, bi := idxs.GetIndexNumber(i), idxs.GetIndexNumber(j) - distance := bi.Sub(ai) - return ae.Before(be) || (ae.Equal(be) && distance < 3) - }) - // find a discontinuity and rotate - i := 1 - for ; i < idxs.Len(); i++ { - if idxs.GetIndexNumber(i-1).Add(1) != idxs.GetIndexNumber(i).Add(0) { - break - } - } - idxs = idxs.Rotate(i) -} diff --git a/control/colibri/reservation/index_test.go b/control/colibri/reservation/index_test.go deleted file mode 100644 index f78656495..000000000 --- a/control/colibri/reservation/index_test.go +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2020 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 reservation - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/util" -) - -func TestValidateIndices(t *testing.T) { - idxs := make(Indices, 0) - // up to 3 indices per expiration time - expTime := time.Unix(1, 0) - idx, err := idxs.NewIndex(expTime) - require.NoError(t, err) - require.Equal(t, reservation.IndexNumber(0), idx) - idx, err = idxs.NewIndex(expTime) - require.NoError(t, err) - require.Equal(t, reservation.IndexNumber(1), idx) - idx, err = idxs.NewIndex(expTime) - require.NoError(t, err) - require.Equal(t, reservation.IndexNumber(2), idx) - idxs = idxs[:1] - // exp time is less - _, err = idxs.NewIndex(expTime.Add(-1 * time.Millisecond)) - require.Error(t, err) - require.Len(t, idxs, 1) - // exp time is same - idx, err = idxs.NewIndex(expTime) - require.NoError(t, err) - require.Len(t, idxs, 2) - require.True(t, idxs[1].Idx == idx) - require.True(t, idxs[1].Expiration == expTime) - require.Equal(t, reservation.IndexNumber(1), idx) - idx, err = idxs.NewIndex(expTime) - require.NoError(t, err) - require.Len(t, idxs, 3) - require.True(t, idxs[2].Idx == idx) - require.True(t, idxs[2].Expiration == expTime) - require.Equal(t, reservation.IndexNumber(2), idx) - // too many indices for the same exp time - _, err = idxs.NewIndex(expTime) - require.Error(t, err) - require.Len(t, idxs, 3) - // exp time is greater - expTime = expTime.Add(time.Second) - idx, err = idxs.NewIndex(expTime) - require.NoError(t, err) - require.Len(t, idxs, 4) - require.True(t, idxs[3].Idx == idx) - require.True(t, idxs[3].Expiration == expTime) - require.Equal(t, reservation.IndexNumber(3), idx) - // index number rollover - idxs = Indices{} - idxs.NewIndex(expTime) - require.Len(t, idxs, 1) - idxs[0].Idx = idxs[0].Idx.Sub(1) - idx, err = idxs.NewIndex(expTime) - require.NoError(t, err) - require.True(t, idxs[1].Idx == idx) - require.True(t, idxs[1].Expiration == expTime) - require.Equal(t, reservation.IndexNumber(0), idx) - // more than 16 indices - idxs = Indices{} - for i := 0; i < 16; i++ { - expTime := time.Unix(int64(i), 0) - _, err = idxs.NewIndex(expTime) - require.NoError(t, err) - } - require.Len(t, idxs, 16) - _, err = idxs.NewIndex(expTime.Add(time.Hour)) - require.Error(t, err) - // exp time is before - idxs = Indices{} - expTime = time.Unix(1, 0) - idxs.NewIndex(expTime) - idxs.NewIndex(expTime) - idxs[1].Expiration = expTime.Add(-1 * time.Second) - err = ValidateIndices(idxs) - require.Error(t, err) - // non consecutive indices - idxs = Indices{} - expTime = time.Unix(1, 0) - idxs.NewIndex(expTime) - idxs.NewIndex(expTime) - idxs[1].Idx = 2 - err = ValidateIndices(idxs) - require.Error(t, err) - // more than three indices per exp time - idxs = Indices{} - idxs.NewIndex(expTime) - idxs.NewIndex(expTime) - idxs.NewIndex(expTime) - require.Len(t, idxs, 3) - err = ValidateIndices(idxs) - require.NoError(t, err) - _, err = idxs.NewIndex(expTime) - require.Error(t, err) -} - -func TestIndicesSort(t *testing.T) { - indices := newTestIndices(2, 3, 1) - SortIndices(indices) - require.Len(t, indices, 3) - checkIndicesSorted(t, indices) - // one element - indices = newTestIndices(2) - SortIndices(indices) - require.Len(t, indices, 1) - require.Equal(t, 2, int(indices[0].Idx)) - // empty - indices = Indices{} - SortIndices(indices) - require.Len(t, indices, 0) - // wrap around - indices = newTestIndices(0, 1, 15) - SortIndices(indices) - require.Len(t, indices, 3) - checkIndicesSorted(t, indices) - // full 16 elements - indices = newTestIndices(14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13) - SortIndices(indices) - require.Len(t, indices, 16) - checkIndicesSorted(t, indices) -} - -func newTestIndices(idxs ...int) Indices { - indices := make(Indices, len(idxs)) - for i, idx := range idxs { - indices[i].Expiration = util.SecsToTime(uint32(i/3 + 1)) - indices[i].Idx = reservation.IndexNumber(idx) - } - return indices -} - -func checkIndicesSorted(t *testing.T, idxs Indices) { - t.Helper() - // validate according to valid indices criteria - err := ValidateIndices(idxs) - require.NoError(t, err) -} - -type Index struct { - Idx reservation.IndexNumber - Expiration time.Time -} - -type Indices []Index - -var _ IndicesInterface = (*Indices)(nil) - -func (idxs Indices) Len() int { return len(idxs) } -func (idxs Indices) GetIndexNumber(i int) reservation.IndexNumber { return idxs[i].Idx } -func (idxs Indices) GetExpiration(i int) time.Time { return idxs[i].Expiration } -func (idxs Indices) GetAllocBW(i int) reservation.BWCls { return reservation.BWCls(0) } -func (idxs Indices) GetToken(i int) *reservation.Token { return nil } -func (idxs Indices) Rotate(i int) IndicesInterface { - return append(idxs[i:], idxs[:i]...) -} - -func (idxs *Indices) NewIndex(expTime time.Time) (reservation.IndexNumber, error) { - idx := reservation.IndexNumber(0) - if len(*idxs) > 0 { - idx = (*idxs)[len(*idxs)-1].Idx.Add(1) - } - index := Index{ - Idx: idx, - Expiration: expTime, - } - newIndices := make(Indices, len(*idxs)+1) - copy(newIndices, *idxs) - newIndices[len(newIndices)-1] = index - err := ValidateIndices(newIndices) - if err != nil { - return reservation.IndexNumber(0), err - } - *idxs = newIndices - return idx, nil -} diff --git a/control/colibri/reservation/request.go b/control/colibri/reservation/request.go deleted file mode 100644 index 6d1c7cef3..000000000 --- a/control/colibri/reservation/request.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 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 reservation - -import ( - "github.com/scionproto/scion/pkg/private/serrors" -) - -// RequestMetadata contains information about the request, such as its forwarding path. -// This base struct can be used by any request or response packets. -type RequestMetadata struct { - path ColibriPath // the path the packet came / will go with -} - -// NewRequestMetadata constructs the base Request type. -func NewRequestMetadata(path ColibriPath) (*RequestMetadata, error) { - if path == nil { - return nil, serrors.New("new request with nil path") - } - return &RequestMetadata{ - path: path.Copy(), - }, nil -} - -// Path returns the ColibriPath in this metadata. -func (m *RequestMetadata) Path() ColibriPath { - return m.path -} - -// IsLastAS returns true if this hop is the last one (this AS is the destination). -func (m *RequestMetadata) IsLastAS() bool { - return m.path.IndexOfCurrentHop() == m.path.NumberOfHops()-1 -} diff --git a/control/colibri/reservation/reservationdbtest/BUILD.bazel b/control/colibri/reservation/reservationdbtest/BUILD.bazel deleted file mode 100644 index 76917fb9d..000000000 --- a/control/colibri/reservation/reservationdbtest/BUILD.bazel +++ /dev/null @@ -1,18 +0,0 @@ -load("//tools/lint:go.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["reservationdbtest.go"], - importpath = "github.com/scionproto/scion/control/colibri/reservation/reservationdbtest", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation/e2e:go_default_library", - "//control/colibri/reservation/segment:go_default_library", - "//control/colibri/reservation/segmenttest:go_default_library", - "//control/colibri/reservationstorage/backend:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/util:go_default_library", - "//pkg/private/xtest:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) diff --git a/control/colibri/reservation/reservationdbtest/reservationdbtest.go b/control/colibri/reservation/reservationdbtest/reservationdbtest.go deleted file mode 100644 index 89ccac7dd..000000000 --- a/control/colibri/reservation/reservationdbtest/reservationdbtest.go +++ /dev/null @@ -1,704 +0,0 @@ -// Copyright 2020 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 reservationdbtest - -import ( - "context" - "encoding/binary" - "encoding/hex" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/control/colibri/reservation/e2e" - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/control/colibri/reservation/segmenttest" - "github.com/scionproto/scion/control/colibri/reservationstorage/backend" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/util" - "github.com/scionproto/scion/pkg/private/xtest" -) - -type TestableDB interface { - backend.DB - Prepare(*testing.T, context.Context) -} - -func TestDB(t *testing.T, db TestableDB) { - tests := map[string]func(context.Context, *testing.T, backend.DB){ - "insert segment reservations create ID": testNewSegmentRsv, - "persist segment reservation": testPersistSegmentRsv, - "get segment reservation from ID": testGetSegmentRsvFromID, - "get segment reservations from src/dst": testGetSegmentRsvsFromSrcDstIA, - "get segment reservation from path": testGetSegmentRsvFromPath, - "get all segment reservations": testGetAllSegmentRsvs, - "get segment reservation from IF pair": testGetSegmentRsvsFromIFPair, - "delete segment reservation": testDeleteSegmentRsv, - "delete expired indices": testDeleteExpiredIndices, - "persist e2e reservation": testPersistE2ERsv, - "get e2e reservation from ID": testGetE2ERsvFromID, - "get e2e reservations from segment ones": testGetE2ERsvsOnSegRsv, - } - for name, test := range tests { - t.Run(name, func(t *testing.T) { - ctx := context.Background() - db.Prepare(t, ctx) - test(ctx, t, db) - }) - } -} - -func testNewSegmentRsv(ctx context.Context, t *testing.T, db backend.DB) { - r := newTestReservation(t) - r.Path = segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0) - r.Indices = segment.Indices{} - // no indices - err := db.NewSegmentRsv(ctx, r) - require.NoError(t, err) - require.Equal(t, xtest.MustParseHexString("00000001"), r.ID.Suffix[:]) - rsv, err := db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, rsv) - // at least one index, and change path - token := newToken() - _, err = r.NewIndexFromToken(token, 0, 0) - require.NoError(t, err) - r.Path = segmenttest.NewPathFromComponents(1, "1-ff00:0:1", 2, 1, "1-ff00:0:2", 0) - err = db.NewSegmentRsv(ctx, r) - require.NoError(t, err) - require.Equal(t, xtest.MustParseHexString("00000002"), r.ID.Suffix[:]) - rsv, err = db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, rsv) - // same path should fail - err = db.NewSegmentRsv(ctx, r) - require.Error(t, err) - // different ASID should start with the lowest suffix - r = newTestReservation(t) - r.ID.ASID = xtest.MustParseAS("ff00:1234:1") - err = db.NewSegmentRsv(ctx, r) - require.NoError(t, err) - require.Equal(t, xtest.MustParseHexString("00000001"), r.ID.Suffix[:]) - rsv, err = db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, rsv) -} - -func testPersistSegmentRsv(ctx context.Context, t *testing.T, db backend.DB) { - r := newTestReservation(t) - for i := uint32(1); i < 10; i++ { - _, err := r.NewIndexAtSource(util.SecsToTime(i), 0, 0, 0, 0, reservation.CorePath) - require.NoError(t, err) - } - require.Len(t, r.Indices, 10) - err := db.NewSegmentRsv(ctx, r) - require.NoError(t, err) - rsv, err := db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, rsv) - // now remove one index - err = r.RemoveIndex(0) - require.NoError(t, err) - err = db.PersistSegmentRsv(ctx, r) - require.NoError(t, err) - rsv, err = db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, rsv) - // change ID - r.ID.ASID = xtest.MustParseAS("ff00:1:12") - copy(r.ID.Suffix[:], xtest.MustParseHexString("beefcafe")) - err = db.PersistSegmentRsv(ctx, r) - require.NoError(t, err) - rsv, err = db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, rsv) - // change attributes - r.Ingress = 3 - r.Egress = 4 - r.Path = segmenttest.NewPathFromComponents(3, "1-ff00:0:1", 11, 1, "1-ff00:0:2", 0) - err = db.PersistSegmentRsv(ctx, r) - require.NoError(t, err) - rsv, err = db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, rsv) - // remove 7 more indices, remains 1 index - err = r.RemoveIndex(8) - require.NoError(t, err) - r.Indices[0].Expiration = util.SecsToTime(12345) - r.Indices[0].MinBW = 10 - r.Indices[0].MaxBW = 11 - r.Indices[0].AllocBW = 12 - r.Indices[0].Token = newToken() // change the token - r.Indices[0].Token.BWCls = 8 - err = r.SetIndexConfirmed(r.Indices[0].Idx) - require.NoError(t, err) - err = r.SetIndexActive(r.Indices[0].Idx) - require.NoError(t, err) - err = db.PersistSegmentRsv(ctx, r) - require.NoError(t, err) - rsv, err = db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, rsv) -} - -func testGetSegmentRsvFromID(ctx context.Context, t *testing.T, db backend.DB) { - r := newTestReservation(t) - err := db.NewSegmentRsv(ctx, r) - require.NoError(t, err) - // create new index - expTime := util.SecsToTime(1) - _, err = r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - require.NoError(t, err) - err = db.PersistSegmentRsv(ctx, r) - require.NoError(t, err) - r2, err := db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, r2) - // 14 more indices for a total of 16 - require.Len(t, r.Indices, 2) - for i := 2; i < 16; i++ { - expTime = util.SecsToTime(uint32(i)) - _, err = r.NewIndexAtSource(expTime, reservation.BWCls(i), reservation.BWCls(i), - reservation.BWCls(i), 0, reservation.CorePath) - require.NoError(t, err) - } - require.Len(t, r.Indices, 16) - err = db.PersistSegmentRsv(ctx, r) - require.NoError(t, err) - r2, err = db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, r2) - // wrong ID - ID := r.ID - ID.ASID++ - r2, err = db.GetSegmentRsvFromID(ctx, &ID) - require.NoError(t, err) - require.Nil(t, r2) -} - -func testGetSegmentRsvsFromSrcDstIA(ctx context.Context, t *testing.T, db backend.DB) { - r := newTestReservation(t) - r.Path = segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0) - err := db.NewSegmentRsv(ctx, r) - require.NoError(t, err) - rsvs, err := db.GetSegmentRsvsFromSrcDstIA(ctx, r.Path.GetSrcIA(), r.Path.GetDstIA()) - require.NoError(t, err) - require.Len(t, rsvs, 1) - require.Equal(t, r, rsvs[0]) - // another reservation with same source and destination - r2 := newTestReservation(t) - r2.Path = segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 2, "1-ff00:0:2", 0) - err = db.NewSegmentRsv(ctx, r2) - require.NoError(t, err) - rsvs, err = db.GetSegmentRsvsFromSrcDstIA(ctx, r.Path.GetSrcIA(), r.Path.GetDstIA()) - require.NoError(t, err) - require.Len(t, rsvs, 2) - // compare without order - require.ElementsMatch(t, rsvs, []*segment.Reservation{r, r2}) - // one more with same source different destination - r3 := newTestReservation(t) - r3.Path = segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:3", 0) - err = db.NewSegmentRsv(ctx, r3) - require.NoError(t, err) - rsvs, err = db.GetSegmentRsvsFromSrcDstIA(ctx, r.Path.GetSrcIA(), r.Path.GetDstIA()) - require.NoError(t, err) - require.Len(t, rsvs, 2) - require.ElementsMatch(t, rsvs, []*segment.Reservation{r, r2}) - rsvs, err = db.GetSegmentRsvsFromSrcDstIA(ctx, r.Path.GetSrcIA(), 0) - require.NoError(t, err) - require.Len(t, rsvs, 3) - require.ElementsMatch(t, rsvs, []*segment.Reservation{r, r2, r3}) - // another reservation with unique source but same destination as r3 - r4 := newTestReservation(t) - r4.Path = segmenttest.NewPathFromComponents(0, "1-ff00:0:4", 1, 1, "1-ff00:0:3", 0) - err = db.NewSegmentRsv(ctx, r4) - require.NoError(t, err) - rsvs, err = db.GetSegmentRsvsFromSrcDstIA(ctx, r.Path.GetSrcIA(), r.Path.GetDstIA()) - require.NoError(t, err) - require.Len(t, rsvs, 2) - require.ElementsMatch(t, rsvs, []*segment.Reservation{r, r2}) - rsvs, err = db.GetSegmentRsvsFromSrcDstIA(ctx, r.Path.GetSrcIA(), 0) - require.NoError(t, err) - require.Len(t, rsvs, 3) - require.ElementsMatch(t, rsvs, []*segment.Reservation{r, r2, r3}) - rsvs, err = db.GetSegmentRsvsFromSrcDstIA(ctx, 0, r.Path.GetDstIA()) - require.NoError(t, err) - require.Len(t, rsvs, 2) - require.ElementsMatch(t, rsvs, []*segment.Reservation{r, r2}) - rsvs, err = db.GetSegmentRsvsFromSrcDstIA(ctx, 0, r3.Path.GetDstIA()) - require.NoError(t, err) - require.Len(t, rsvs, 2) - require.ElementsMatch(t, rsvs, []*segment.Reservation{r3, r4}) -} - -func testGetSegmentRsvFromPath(ctx context.Context, t *testing.T, db backend.DB) { - r1 := newTestReservation(t) - r1.Path = segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0) - err := db.NewSegmentRsv(ctx, r1) - require.NoError(t, err) - r2 := newTestReservation(t) - r2.Path = segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:3", 0) - err = db.NewSegmentRsv(ctx, r2) - require.NoError(t, err) - // retrieve - r, err := db.GetSegmentRsvFromPath(ctx, r1.Path) - require.NoError(t, err) - require.Equal(t, r1, r) - r, err = db.GetSegmentRsvFromPath(ctx, r2.Path) - require.NoError(t, err) - require.Equal(t, r2, r) -} - -func testGetAllSegmentRsvs(ctx context.Context, t *testing.T, db backend.DB) { - // empty - rsvs, err := db.GetAllSegmentRsvs(ctx) - require.NoError(t, err) - require.Empty(t, rsvs) - // insert in1,eg1 ; in2,eg1 ; in1,eg2 - r1 := newTestReservation(t) - r1.Ingress = 11 - r1.Egress = 12 - err = db.NewSegmentRsv(ctx, r1) - require.NoError(t, err) - r2 := newTestReservation(t) - r2.Ingress = 21 - r2.Egress = 12 - err = db.NewSegmentRsv(ctx, r2) - require.NoError(t, err) - r3 := newTestReservation(t) - r3.Ingress = 11 - r3.Egress = 22 - err = db.NewSegmentRsv(ctx, r3) - require.NoError(t, err) - // retrieve them - rsvs, err = db.GetAllSegmentRsvs(ctx) - require.NoError(t, err) - expected := []*segment.Reservation{r1, r2, r3} - require.ElementsMatch(t, expected, rsvs) -} - -func testGetSegmentRsvsFromIFPair(ctx context.Context, t *testing.T, db backend.DB) { - // insert in1,e1 ; in2,e1 ; in1,e2 - r1 := newTestReservation(t) - r1.Ingress = 11 - r1.Egress = 12 - err := db.NewSegmentRsv(ctx, r1) - require.NoError(t, err) - r2 := newTestReservation(t) - r2.Ingress = 21 - r2.Egress = 12 - err = db.NewSegmentRsv(ctx, r2) - require.NoError(t, err) - r3 := newTestReservation(t) - r3.Ingress = 11 - r3.Egress = 22 - err = db.NewSegmentRsv(ctx, r3) - require.NoError(t, err) - // query with a specific pair - rsvs, err := db.GetSegmentRsvsFromIFPair(ctx, &r1.Ingress, &r1.Egress) - require.NoError(t, err) - require.Len(t, rsvs, 1) - expected := []*segment.Reservation{r1} - require.ElementsMatch(t, expected, rsvs) - // any ingress - rsvs, err = db.GetSegmentRsvsFromIFPair(ctx, nil, &r1.Egress) - require.NoError(t, err) - require.Len(t, rsvs, 2) - expected = []*segment.Reservation{r1, r2} - require.ElementsMatch(t, expected, rsvs) - // any egress - rsvs, err = db.GetSegmentRsvsFromIFPair(ctx, &r1.Ingress, nil) - require.NoError(t, err) - require.Len(t, rsvs, 2) - expected = []*segment.Reservation{r1, r3} - require.ElementsMatch(t, expected, rsvs) - // no matches - var inexistentIngress uint16 = 222 - rsvs, err = db.GetSegmentRsvsFromIFPair(ctx, &inexistentIngress, nil) - require.NoError(t, err) - require.Len(t, rsvs, 0) - // bad query - _, err = db.GetSegmentRsvsFromIFPair(ctx, nil, nil) - require.Error(t, err) -} - -func testDeleteSegmentRsv(ctx context.Context, t *testing.T, db backend.DB) { - r := newTestReservation(t) - err := db.NewSegmentRsv(ctx, r) - require.NoError(t, err) - err = db.DeleteSegmentRsv(ctx, &r.ID) - require.NoError(t, err) - rsv, err := db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Nil(t, rsv) - // with no indices - r = newTestReservation(t) - r.Indices = segment.Indices{} - err = db.NewSegmentRsv(ctx, r) - require.NoError(t, err) - err = db.DeleteSegmentRsv(ctx, &r.ID) - require.NoError(t, err) - rsv, err = db.GetSegmentRsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Nil(t, rsv) -} - -func testDeleteExpiredIndices(ctx context.Context, t *testing.T, db backend.DB) { - // create seg. and e2e reservations that have indices expiring at different times. - // rX stands for segment rsv. and eX for an e2e. Twice the same symbol means another index. - // timeline: e1...r1...r2,r3...e2,e3...e3,e4...r3,r4...e5 - // 1 2 3 4 5 6 1000 - // Each eX is linked to a rX, being X the same for both. But e5 is linked to r4. - - // r1, e1 - segIds := make([]reservation.SegmentID, 0) - r := newTestReservation(t) - r.Indices[0].Expiration = util.SecsToTime(2) - err := db.NewSegmentRsv(ctx, r) // save r1 - require.NoError(t, err) - segIds = append(segIds, r.ID) - e := newTestE2EReservation(t) - e.ID.ASID = xtest.MustParseAS("ff00:0:1") - e.SegmentReservations = []*segment.Reservation{r} - e.Indices[0].Expiration = util.SecsToTime(1) - err = db.PersistE2ERsv(ctx, e) // save e1 - require.NoError(t, err) - // r2, e2 - r.Indices[0].Expiration = util.SecsToTime(3) - err = db.NewSegmentRsv(ctx, r) // save r2 - require.NoError(t, err) - segIds = append(segIds, r.ID) - e.ID.ASID = xtest.MustParseAS("ff00:0:2") - e.SegmentReservations = []*segment.Reservation{r} - e.Indices[0].Expiration = util.SecsToTime(4) - err = db.PersistE2ERsv(ctx, e) // save e2 - require.NoError(t, err) - // r3, e3 - r.Indices[0].Expiration = util.SecsToTime(3) - r.NewIndexAtSource(util.SecsToTime(6), 1, 3, 2, 5, reservation.CorePath) - err = db.NewSegmentRsv(ctx, r) // save r3 - require.NoError(t, err) - segIds = append(segIds, r.ID) - e.ID.ASID = xtest.MustParseAS("ff00:0:3") - e.SegmentReservations = []*segment.Reservation{r} - e.Indices[0].Expiration = util.SecsToTime(4) - _, err = e.NewIndex(util.SecsToTime(5)) - require.NoError(t, err) - err = db.PersistE2ERsv(ctx, e) // save e3 - require.NoError(t, err) - // r4, e4 - r.Indices = r.Indices[:1] - r.Indices[0].Expiration = util.SecsToTime(6) - err = db.NewSegmentRsv(ctx, r) // save r4 - require.NoError(t, err) - segIds = append(segIds, r.ID) - e.Indices = e.Indices[:1] - e.Indices[0].Expiration = util.SecsToTime(5) - e.ID.ASID = xtest.MustParseAS("ff00:0:4") - e.SegmentReservations = []*segment.Reservation{r} - err = db.PersistE2ERsv(ctx, e) // save e4 - require.NoError(t, err) - // e5 - e.ID.ASID = xtest.MustParseAS("ff00:0:5") - e.SegmentReservations = []*segment.Reservation{r} - e.Indices[0].Expiration = util.SecsToTime(1000) - err = db.PersistE2ERsv(ctx, e) // save e5 - require.NoError(t, err) - - // second 1: nothing deleted - c, err := db.DeleteExpiredIndices(ctx, util.SecsToTime(1)) - require.NoError(t, err) - require.Equal(t, 0, c) - rsvs, err := db.GetSegmentRsvsFromIFPair(ctx, &r.Ingress, &r.Egress) // get all seg rsvs - require.NoError(t, err) - require.Len(t, rsvs, 4) - e2es := getAllE2ERsvsOnSegmentRsvs(ctx, t, db, segIds) - require.Len(t, e2es, 5) - // second 2, in DB: r1...r2,r3...e2,e3...e3,e4...r3,r4...e5 - c, err = db.DeleteExpiredIndices(ctx, util.SecsToTime(2)) - require.NoError(t, err) - require.Equal(t, 1, c) - rsvs, err = db.GetSegmentRsvsFromIFPair(ctx, &r.Ingress, &r.Egress) - require.NoError(t, err) - require.Len(t, rsvs, 4) - e2es = getAllE2ERsvsOnSegmentRsvs(ctx, t, db, segIds) - require.Len(t, e2es, 4) - // second 3: in DB: r2,r3...e2,e3...e3,e4...r3,r4...e5 - c, err = db.DeleteExpiredIndices(ctx, util.SecsToTime(3)) - require.NoError(t, err) - require.Equal(t, 1, c) - rsvs, err = db.GetSegmentRsvsFromIFPair(ctx, &r.Ingress, &r.Egress) - require.NoError(t, err) - require.Len(t, rsvs, 3) - e2es = getAllE2ERsvsOnSegmentRsvs(ctx, t, db, segIds) - require.Len(t, e2es, 4) - // second 4: in DB: e2,e3...e3,e4...r3,r4...e5 - c, err = db.DeleteExpiredIndices(ctx, util.SecsToTime(4)) - require.NoError(t, err) - require.Equal(t, 2, c) - rsvs, err = db.GetSegmentRsvsFromIFPair(ctx, &r.Ingress, &r.Egress) - require.NoError(t, err) - require.Len(t, rsvs, 2) - e2es = getAllE2ERsvsOnSegmentRsvs(ctx, t, db, segIds) - require.Len(t, e2es, 3) // r2 is gone, cascades for e2 - // second 5: in DB: e3,e4...r3,r4...e5 - c, err = db.DeleteExpiredIndices(ctx, util.SecsToTime(5)) - require.NoError(t, err) - require.Equal(t, 2, c) - rsvs, err = db.GetSegmentRsvsFromIFPair(ctx, &r.Ingress, &r.Egress) - require.NoError(t, err) - require.Len(t, rsvs, 2) - e2es = getAllE2ERsvsOnSegmentRsvs(ctx, t, db, segIds) - require.Len(t, e2es, 3) - // second 6: in DB: r3,r4...e5 - c, err = db.DeleteExpiredIndices(ctx, util.SecsToTime(6)) - require.NoError(t, err) - require.Equal(t, 2, c) - rsvs, err = db.GetSegmentRsvsFromIFPair(ctx, &r.Ingress, &r.Egress) - require.NoError(t, err) - require.Len(t, rsvs, 2) - e2es = getAllE2ERsvsOnSegmentRsvs(ctx, t, db, segIds) - require.Len(t, e2es, 1) - // second 7, in DB: nothing - c, err = db.DeleteExpiredIndices(ctx, util.SecsToTime(7)) - require.NoError(t, err) - require.Equal(t, 2, c) - rsvs, err = db.GetSegmentRsvsFromIFPair(ctx, &r.Ingress, &r.Egress) - require.NoError(t, err) - require.Len(t, rsvs, 0) - e2es = getAllE2ERsvsOnSegmentRsvs(ctx, t, db, segIds) - require.Len(t, e2es, 0) // r4 is gone, cascades for e5 -} - -func testPersistE2ERsv(ctx context.Context, t *testing.T, db backend.DB) { - r1 := newTestE2EReservation(t) - for _, seg := range r1.SegmentReservations { - err := db.PersistSegmentRsv(ctx, seg) - require.NoError(t, err) - } - err := db.PersistE2ERsv(ctx, r1) - require.NoError(t, err) - // get it back - rsv, err := db.GetE2ERsvFromID(ctx, &r1.ID) - require.NoError(t, err) - require.Equal(t, r1, rsv) - // modify - r2 := rsv - for i := range r2.ID.Suffix { - r2.ID.Suffix[i] = byte(i) - } - for i := uint32(2); i < 16; i++ { // add 14 more indices - _, err = r2.NewIndex(util.SecsToTime(i)) - require.NoError(t, err) - } - for i := 0; i < 2; i++ { - seg := newTestReservation(t) - seg.ID.ASID = xtest.MustParseAS(fmt.Sprintf("ff00:2:%d", i+1)) - for j := uint32(1); j < 16; j++ { - _, err := seg.NewIndexAtSource(util.SecsToTime(j), 1, 3, 2, 5, reservation.CorePath) - require.NoError(t, err) - } - err := db.PersistSegmentRsv(ctx, seg) - require.NoError(t, err) - r2.SegmentReservations = append(r2.SegmentReservations, seg) - } - err = db.PersistE2ERsv(ctx, r2) - require.NoError(t, err) - rsv, err = db.GetE2ERsvFromID(ctx, &r2.ID) - require.NoError(t, err) - require.Equal(t, r2, rsv) - // check the other reservation was left intact - rsv, err = db.GetE2ERsvFromID(ctx, &r1.ID) - require.NoError(t, err) - require.Equal(t, r1, rsv) - // try to persist an e2e reservation without persisting its associated segment reservation - r := newTestE2EReservation(t) - r.SegmentReservations[0].ID.ASID = xtest.MustParseAS("ff00:3:1") - err = db.PersistE2ERsv(ctx, r) - require.Error(t, err) - // after persisting the segment one, it will work - err = db.PersistSegmentRsv(ctx, r.SegmentReservations[0]) - require.NoError(t, err) - err = db.PersistE2ERsv(ctx, r) - require.NoError(t, err) -} - -func testGetE2ERsvFromID(ctx context.Context, t *testing.T, db backend.DB) { - // create several e2e reservations, with one segment reservations in common, and two not - checkThisRsvs := map[int]*e2e.Reservation{1: nil, 16: nil, 50: nil, 100: nil} - for i := 1; i <= 100; i++ { - r := newTestE2EReservation(t) - binary.BigEndian.PutUint32(r.ID.Suffix[:], uint32(i)) - _, found := checkThisRsvs[i] - if found { - checkThisRsvs[i] = r - } - for j := 0; j < 2; j++ { - seg := newTestReservation(t) - seg.ID.ASID = xtest.MustParseAS(fmt.Sprintf("ff00:%d:%d", i, j+1)) - err := db.PersistSegmentRsv(ctx, seg) - require.NoError(t, err) - } - for _, seg := range r.SegmentReservations { - segRsv, err := db.GetSegmentRsvFromID(ctx, &seg.ID) - require.NoError(t, err) - if segRsv == nil { - err := db.PersistSegmentRsv(ctx, seg) - require.NoError(t, err) - } - } - err := db.PersistE2ERsv(ctx, r) - require.NoError(t, err) - } - // now check - for i, r := range checkThisRsvs { - ID := reservation.E2EID{ASID: xtest.MustParseAS("ff00:0:1")} - binary.BigEndian.PutUint32(ID.Suffix[:], uint32(i)) - rsv, err := db.GetE2ERsvFromID(ctx, &ID) - require.NoError(t, err) - require.Equal(t, r, rsv) - } - // with 8 indices starting at index number 14 - r := newTestE2EReservation(t) - r.Indices = e2e.Indices{} - for i := uint32(2); i < 18; i++ { - _, err := r.NewIndex(util.SecsToTime(i / 2)) - require.NoError(t, err) - } - r.Indices = r.Indices[14:] - for i := uint32(18); i < 20; i++ { - _, err := r.NewIndex(util.SecsToTime(i / 2)) - require.NoError(t, err) - } - err := db.PersistE2ERsv(ctx, r) - require.NoError(t, err) - rsv, err := db.GetE2ERsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, rsv) - // 16 indices - require.Len(t, r.Indices, 4) - for i := uint32(20); i < 32; i++ { - _, err := r.NewIndex(util.SecsToTime(i / 2)) - require.NoError(t, err) - } - require.Len(t, r.Indices, 16) - err = db.PersistE2ERsv(ctx, r) - require.NoError(t, err) - rsv, err = db.GetE2ERsvFromID(ctx, &r.ID) - require.NoError(t, err) - require.Equal(t, r, rsv) - // not present in DB - ID, err := reservation.NewE2EID(xtest.MustParseAS("ff00:2222:3333"), - xtest.MustParseHexString("0123456789abcdef0123")) - require.NoError(t, err) - rsv, err = db.GetE2ERsvFromID(ctx, ID) - require.NoError(t, err) - require.Nil(t, rsv) -} - -func testGetE2ERsvsOnSegRsv(ctx context.Context, t *testing.T, db backend.DB) { - s1 := newTestReservation(t) - err := db.NewSegmentRsv(ctx, s1) - require.NoError(t, err) - s2 := newTestReservation(t) - err = db.NewSegmentRsv(ctx, s2) - require.NoError(t, err) - // e2e reservations - e1 := newTestE2EReservation(t) - e1.ID.ASID = xtest.MustParseAS("ff00:0:1") - e1.SegmentReservations = []*segment.Reservation{s1} - err = db.PersistE2ERsv(ctx, e1) - require.NoError(t, err) - e2 := newTestE2EReservation(t) - e2.ID.ASID = xtest.MustParseAS("ff00:0:2") - e2.SegmentReservations = []*segment.Reservation{s2} - err = db.PersistE2ERsv(ctx, e2) - require.NoError(t, err) - e3 := newTestE2EReservation(t) - e3.ID.ASID = xtest.MustParseAS("ff00:0:3") - e3.SegmentReservations = []*segment.Reservation{s1, s2} - err = db.PersistE2ERsv(ctx, e3) - require.NoError(t, err) - // test - rsvs, err := db.GetE2ERsvsOnSegRsv(ctx, &s1.ID) - require.NoError(t, err) - require.ElementsMatch(t, rsvs, []*e2e.Reservation{e1, e3}) - rsvs, err = db.GetE2ERsvsOnSegRsv(ctx, &s2.ID) - require.NoError(t, err) - require.ElementsMatch(t, rsvs, []*e2e.Reservation{e2, e3}) -} - -// newToken just returns a token that can be serialized. This one has two HopFields. -func newToken() *reservation.Token { - t, err := reservation.TokenFromRaw(xtest.MustParseHexString( - "0000000000040500003f001002bad1ce003f001002facade")) - if err != nil { - panic("invalid serialized token") - } - return t -} - -func newTestReservation(t *testing.T) *segment.Reservation { - t.Helper() - r := segment.NewReservation() - r.Path = segment.ReservationTransparentPath{} - r.ID.ASID = xtest.MustParseAS("ff00:0:1") - r.Ingress = 0 - r.Egress = 1 - r.TrafficSplit = 3 - r.PathEndProps = reservation.EndLocal | reservation.StartLocal - expTime := util.SecsToTime(1) - _, err := r.NewIndexAtSource(expTime, 1, 3, 2, 5, reservation.CorePath) - require.NoError(t, err) - err = r.SetIndexConfirmed(0) - require.NoError(t, err) - return r -} - -func newTestE2EReservation(t *testing.T) *e2e.Reservation { - rsv := &e2e.Reservation{ - ID: reservation.E2EID{ - ASID: xtest.MustParseAS("ff00:0:1"), - }, - SegmentReservations: []*segment.Reservation{ - newTestReservation(t), - }, - } - expTime := util.SecsToTime(1) - _, err := rsv.NewIndex(expTime) - require.NoError(t, err) - return rsv -} - -func getAllE2ERsvsOnSegmentRsvs(ctx context.Context, t *testing.T, db backend.DB, - ids []reservation.SegmentID) []*e2e.Reservation { - - set := make(map[string]struct{}) - rsvs := make([]*e2e.Reservation, 0) - for _, id := range ids { - rs, err := db.GetE2ERsvsOnSegRsv(ctx, &id) - require.NoError(t, err) - for _, r := range rs { - s := hex.EncodeToString(r.ID.ToRaw()) - _, found := set[s] - if !found { - rsvs = append(rsvs, r) - set[s] = struct{}{} - } - } - } - return rsvs -} diff --git a/control/colibri/reservation/segment/BUILD.bazel b/control/colibri/reservation/segment/BUILD.bazel deleted file mode 100644 index 99ca4a643..000000000 --- a/control/colibri/reservation/segment/BUILD.bazel +++ /dev/null @@ -1,37 +0,0 @@ -load("//tools/lint:go.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "index.go", - "path.go", - "request.go", - "reservation.go", - "response.go", - ], - importpath = "github.com/scionproto/scion/control/colibri/reservation/segment", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation:go_default_library", - "//pkg/addr:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/serrors:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "export_test.go", - "path_test.go", - "reservation_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//control/colibri/reservation/segmenttest:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/util:go_default_library", - "//pkg/private/xtest:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) diff --git a/control/colibri/reservation/segment/admission/BUILD.bazel b/control/colibri/reservation/segment/admission/BUILD.bazel deleted file mode 100644 index bb2464654..000000000 --- a/control/colibri/reservation/segment/admission/BUILD.bazel +++ /dev/null @@ -1,9 +0,0 @@ -load("//tools/lint:go.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["admitter.go"], - importpath = "github.com/scionproto/scion/control/colibri/reservation/segment/admission", - visibility = ["//visibility:public"], - deps = ["//control/colibri/reservation/segment:go_default_library"], -) diff --git a/control/colibri/reservation/segment/admission/admitter.go b/control/colibri/reservation/segment/admission/admitter.go deleted file mode 100644 index aef129ecb..000000000 --- a/control/colibri/reservation/segment/admission/admitter.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2020 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 admission - -import ( - "context" - - "github.com/scionproto/scion/control/colibri/reservation/segment" -) - -// Admitter specifies what an admission entity has to implement to govern the segment admission. -type Admitter interface { - // req will be modified with the allowed and maximum bandwidths if they were computed. - // It can also return an error. - AdmitRsv(ctx context.Context, req *segment.SetupReq) error -} diff --git a/control/colibri/reservation/segment/admission/impl/BUILD.bazel b/control/colibri/reservation/segment/admission/impl/BUILD.bazel deleted file mode 100644 index 69600c1f8..000000000 --- a/control/colibri/reservation/segment/admission/impl/BUILD.bazel +++ /dev/null @@ -1,33 +0,0 @@ -load("//tools/lint:go.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["stateless.go"], - importpath = "github.com/scionproto/scion/control/colibri/reservation/segment/admission/impl", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation:go_default_library", - "//control/colibri/reservation/segment:go_default_library", - "//control/colibri/reservation/segment/admission:go_default_library", - "//control/colibri/reservationstorage/backend:go_default_library", - "//pkg/addr:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/serrors:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["stateless_test.go"], - embed = [":go_default_library"], - deps = [ - "//control/colibri/reservation:go_default_library", - "//control/colibri/reservation/segment:go_default_library", - "//control/colibri/reservationstorage/backend/mock_backend:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/util:go_default_library", - "//pkg/private/xtest:go_default_library", - "@com_github_golang_mock//gomock:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) diff --git a/control/colibri/reservation/segment/admission/impl/stateless.go b/control/colibri/reservation/segment/admission/impl/stateless.go deleted file mode 100644 index 13c5bdeea..000000000 --- a/control/colibri/reservation/segment/admission/impl/stateless.go +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright 2020 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 impl - -import ( - "context" - "math" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/control/colibri/reservation/segment/admission" - "github.com/scionproto/scion/control/colibri/reservationstorage/backend" - "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" -) - -// StatelessAdmission can admit a segment reservation without any state other than the DB. -type StatelessAdmission struct { - DB backend.DB - Capacities base.Capacities // aka capacity matrix - Delta float64 // fraction of free BW that can be reserved in one request -} - -var _ admission.Admitter = (*StatelessAdmission)(nil) - -// AdmitRsv admits a segment reservation. The request will be modified with the allowed and -// maximum bandwidths if they were computed. It can also return an error that must be checked. -func (a *StatelessAdmission) AdmitRsv(ctx context.Context, req *segment.SetupReq) error { - avail, err := a.availableBW(ctx, req) - if err != nil { - return serrors.WrapStr("cannot compute available bandwidth", err, "segment_id", req.ID) - } - ideal, err := a.idealBW(ctx, req) - if err != nil { - return serrors.WrapStr("cannot compute ideal bandwidth", err, "segment_id", req.ID) - } - maxAlloc := reservation.BWClsFromBW(minBW(avail, ideal)) - bead := reservation.AllocationBead{ - AllocBW: reservation.MinBWCls(maxAlloc, req.MaxBW), - MaxBW: maxAlloc, - } - req.AllocTrail = append(req.AllocTrail, bead) - if maxAlloc < req.MinBW { - return serrors.New("admission denied", "maxalloc", maxAlloc, "minbw", req.MinBW, - "segment_id", req.ID) - } - return nil -} - -func (a *StatelessAdmission) availableBW(ctx context.Context, req *segment.SetupReq) ( - uint64, error) { - - sameIngress, err := a.DB.GetSegmentRsvsFromIFPair(ctx, &req.Ingress, nil) - if err != nil { - return 0, serrors.WrapStr("cannot get reservations using ingress", err, - "ingress", req.Ingress) - } - sameEgress, err := a.DB.GetSegmentRsvsFromIFPair(ctx, nil, &req.Egress) - if err != nil { - return 0, serrors.WrapStr("cannot get reservations using egress", err, - "egress", req.Egress) - } - bwIngress := sumMaxBlockedBW(sameIngress, req.ID) - freeIngress := a.Capacities.CapacityIngress(req.Ingress) - bwIngress - bwEgress := sumMaxBlockedBW(sameEgress, req.ID) - freeEgress := a.Capacities.CapacityEgress(req.Egress) - bwEgress - // `free` excludes the BW from an existing reservation if its ID equals the request's ID - free := float64(minBW(freeIngress, freeEgress)) - return uint64(free * a.Delta), nil -} - -func (a *StatelessAdmission) idealBW(ctx context.Context, req *segment.SetupReq) (uint64, error) { - demsPerSrcRegIngress, err := a.computeTempDemands(ctx, req.Ingress, req) - if err != nil { - return 0, serrors.WrapStr("cannot compute temporary demands", err) - } - tubeRatio, err := a.tubeRatio(ctx, req, demsPerSrcRegIngress) - if err != nil { - return 0, serrors.WrapStr("cannot compute tube ratio", err) - } - linkRatio, err := a.linkRatio(ctx, req, demsPerSrcRegIngress) - if err != nil { - return 0, serrors.WrapStr("cannot compute link ratio", err) - } - cap := float64(a.Capacities.CapacityEgress(req.Egress)) - return uint64(cap * tubeRatio * linkRatio), nil -} - -func (a *StatelessAdmission) tubeRatio(ctx context.Context, req *segment.SetupReq, - demsPerSrc demPerSource) (float64, error) { - - // TODO(juagargi) to avoid calling several times to computeTempDemands, refactor the - // type holding the results, so that it stores capReqDem per source per ingress interface. - // InScalFctr and EgScalFctr will be stored independently, per source per interface. - transitDemand, err := a.transitDemand(ctx, req, req.Ingress, demsPerSrc) - if err != nil { - return 0, serrors.WrapStr("cannot compute transit demand", err) - } - capIn := a.Capacities.CapacityIngress(req.Ingress) - numerator := minBW(capIn, transitDemand) - var sum uint64 - for _, in := range a.Capacities.IngressInterfaces() { - demandsForThisIngress, err := a.computeTempDemands(ctx, in, req) - if err != nil { - return 0, serrors.WrapStr("cannot compute transit demand", err) - } - dem, err := a.transitDemand(ctx, req, in, demandsForThisIngress) - if err != nil { - return 0, serrors.WrapStr("cannot compute transit demand", err) - } - sum += minBW(a.Capacities.CapacityIngress(in), dem) - } - return float64(numerator) / float64(sum), nil -} - -func (a *StatelessAdmission) linkRatio(ctx context.Context, req *segment.SetupReq, - demsPerSrc demPerSource) (float64, error) { - - capEg := a.Capacities.CapacityEgress(req.Egress) - demEg := demsPerSrc[req.ID.ASID].eg - - prevBW := req.AllocTrail.MinMax().ToKbps() // min of maxBW in the trail - var egScalFctr float64 - if demEg != 0 { - egScalFctr = float64(minBW(capEg, demEg)) / float64(demEg) - } - numerator := egScalFctr * float64(prevBW) - egScalFctrs := make(map[addr.AS]float64) - for src, dem := range demsPerSrc { - var egScalFctr float64 - if dem.eg != 0 { - egScalFctr = float64(minBW(capEg, dem.eg)) / float64(dem.eg) - } - egScalFctrs[src] = egScalFctr - } - rsvs, err := a.DB.GetAllSegmentRsvs(ctx) - if err != nil { - return 0, serrors.WrapStr("cannot list all reservations", err) - } - srcAllocPerSrc := make(map[addr.AS]uint64) - for _, rsv := range rsvs { - if rsv.ID == req.ID { - continue - } - src := rsv.ID.ASID - srcAlloc := rsv.MaxBlockedBW() - srcAllocPerSrc[src] += srcAlloc - } - if _, found := srcAllocPerSrc[req.ID.ASID]; !found { - // add the source of the request, if not already present - srcAllocPerSrc[req.ID.ASID] = 0 // the value of the srcAlloc itself won't be used - } - // TODO(juagargi) after debugging, integrate this loop into the previous one: - var denom float64 - for src, srcAlloc := range srcAllocPerSrc { - if src == req.ID.ASID { - srcAlloc += prevBW - } - egScalFctr, found := egScalFctrs[src] - if !found { - return 0, serrors.New("cannot compute link ratio, internal error: "+ - "source not found in the egress scale factors", "src", src) - } - denom += float64(srcAlloc) * egScalFctr - } - return numerator / denom, nil -} - -// demands represents the demands for a given source, and a specific ingress-egress interface pair. -// from the admission spec: srcDem, inDem and egDem for a given source. -type demands struct { - src, in, eg uint64 -} - -// demsPerSrc is used in the transit demand computation. -type demPerSource map[addr.AS]demands - -// computeTempDemands will compute inDem, egDem and srcDem grouped by source, for all sources. -// this is, all cap. requested demands from all reservations, grouped by source, that enter -// the AS at "ingress" and exit at "egress". It also stores all the source demands that enter -// the AS at "ingress", and the source demands that exit the AS at "egress". -func (a *StatelessAdmission) computeTempDemands(ctx context.Context, ingress uint16, - req *segment.SetupReq) (demPerSource, error) { - - // TODO(juagargi) consider adding a call to db to get all srcDem,inDem,egDem grouped by source - rsvs, err := a.DB.GetAllSegmentRsvs(ctx) - if err != nil { - return nil, serrors.WrapStr("cannot obtain segment rsvs. from ingress/egress pair", err) - } - capIn := a.Capacities.CapacityIngress(ingress) - capEg := a.Capacities.CapacityEgress(req.Egress) - // srcDem, inDem and egDem grouped by source - demsPerSrc := make(demPerSource) - for _, rsv := range rsvs { - if rsv.ID == req.ID { - continue - } - dem := min3BW(capIn, capEg, rsv.MaxRequestedBW()) // capReqDem in the formulas - bucket := demsPerSrc[rsv.ID.ASID] - if rsv.Ingress == ingress { - bucket.in += dem - } - if rsv.Egress == req.Egress { - bucket.eg += dem - } - if rsv.Ingress == ingress && rsv.Egress == req.Egress { - bucket.src += dem - } - demsPerSrc[rsv.ID.ASID] = bucket - } - // add the request itself to whatever we have for that source - bucket := demsPerSrc[req.ID.ASID] - dem := min3BW(capIn, capEg, req.MaxBW.ToKbps()) - if req.Ingress == ingress { - bucket.in += dem - } - if req.Egress == req.Egress { - bucket.eg += dem - } - if req.Ingress == ingress && req.Egress == req.Egress { - bucket.src += dem - } - demsPerSrc[req.ID.ASID] = bucket - - return demsPerSrc, nil -} - -// transitDemand computes the transit demand from ingress to req.Egress. The parameter -// demsPerSrc must hold the inDem, egDem and srcDem of all reservations, grouped by source, and -// for an ingress interface = ingress parameter. -func (a *StatelessAdmission) transitDemand(ctx context.Context, req *segment.SetupReq, - ingress uint16, demsPerSrc demPerSource) (uint64, error) { - - capIn := a.Capacities.CapacityIngress(ingress) - capEg := a.Capacities.CapacityEgress(req.Egress) - // TODO(juagargi) adjSrcDem is not needed, remove after finishing debugging the admission - adjSrcDem := make(map[addr.AS]uint64) // every adjSrcDem grouped by source - for src, dems := range demsPerSrc { - var inScalFctr float64 = 1. - if dems.in != 0 { - inScalFctr = float64(minBW(capIn, dems.in)) / float64(dems.in) - } - var egScalFctr float64 = 1. - if dems.eg != 0 { - egScalFctr = float64(minBW(capEg, dems.eg)) / float64(dems.eg) - } - adjSrcDem[src] = uint64(math.Min(inScalFctr, egScalFctr) * float64(dems.src)) - } - // now reduce adjSrcDem - var transitDem uint64 - for _, dem := range adjSrcDem { - transitDem += dem - } - - return transitDem, nil -} - -// sumMaxBlockedBW adds up all the max blocked bandwidth by the reservation, for all reservations, -// iff they don't have the same ID as "excludeThisRsv". -func sumMaxBlockedBW(rsvs []*segment.Reservation, excludeThisRsv reservation.SegmentID) uint64 { - var total uint64 - for _, r := range rsvs { - if r.ID != excludeThisRsv { - total += r.MaxBlockedBW() - } - } - return total -} - -func minBW(a, b uint64) uint64 { - if a < b { - return a - } - return b -} - -func min3BW(a, b, c uint64) uint64 { - return minBW(minBW(a, b), c) -} diff --git a/control/colibri/reservation/segment/admission/impl/stateless_test.go b/control/colibri/reservation/segment/admission/impl/stateless_test.go deleted file mode 100644 index 7a024efeb..000000000 --- a/control/colibri/reservation/segment/admission/impl/stateless_test.go +++ /dev/null @@ -1,522 +0,0 @@ -// Copyright 2020 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 impl - -import ( - "context" - "testing" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/require" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/control/colibri/reservationstorage/backend/mock_backend" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/util" - "github.com/scionproto/scion/pkg/private/xtest" -) - -func TestSumMaxBlockedBW(t *testing.T) { - cases := map[string]struct { - blockedBW uint64 - rsvsFcn func() []*segment.Reservation - excludeID string - }{ - "empty": { - blockedBW: 0, - rsvsFcn: func() []*segment.Reservation { - return nil - }, - excludeID: "ff0000010001beefcafe", - }, - "one reservation": { - blockedBW: reservation.BWCls(5).ToKbps(), - rsvsFcn: func() []*segment.Reservation { - rsv := testNewRsv(t, "ff00:1:1", "01234567", 1, 2, 5, 5, 5) - _, err := rsv.NewIndexAtSource(util.SecsToTime(3), 1, 1, 1, 1, reservation.CorePath) - require.NoError(t, err) - _, err = rsv.NewIndexAtSource(util.SecsToTime(3), 1, 1, 1, 1, reservation.CorePath) - require.NoError(t, err) - return []*segment.Reservation{rsv} - }, - excludeID: "ff0000010001beefcafe", - }, - "one reservation but excluded": { - blockedBW: 0, - rsvsFcn: func() []*segment.Reservation { - rsv := testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 5, 5) - _, err := rsv.NewIndexAtSource(util.SecsToTime(3), 1, 1, 1, 1, reservation.CorePath) - require.NoError(t, err) - _, err = rsv.NewIndexAtSource(util.SecsToTime(3), 1, 1, 1, 1, reservation.CorePath) - require.NoError(t, err) - return []*segment.Reservation{rsv} - }, - excludeID: "ff0000010001beefcafe", - }, - "many reservations": { - blockedBW: 309, // 181 + 128 - rsvsFcn: func() []*segment.Reservation { - rsv := testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 5, 5) - _, err := rsv.NewIndexAtSource(util.SecsToTime(3), 1, 17, 7, 1, - reservation.CorePath) - require.NoError(t, err) - rsvs := []*segment.Reservation{rsv} - - rsv = testNewRsv(t, "ff00:1:1", "01234567", 1, 2, 5, 5, 5) - _, err = rsv.NewIndexAtSource(util.SecsToTime(3), 1, 8, 8, 1, reservation.CorePath) - require.NoError(t, err) - _, err = rsv.NewIndexAtSource(util.SecsToTime(3), 1, 7, 7, 1, reservation.CorePath) - require.NoError(t, err) - rsvs = append(rsvs, rsv) - - rsv = testNewRsv(t, "ff00:1:2", "01234567", 1, 2, 5, 5, 5) - _, err = rsv.NewIndexAtSource(util.SecsToTime(2), 1, 7, 7, 1, reservation.CorePath) - require.NoError(t, err) - rsvs = append(rsvs, rsv) - - return rsvs - }, - excludeID: "ff0000010001beefcafe", - }, - } - - for name, tc := range cases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - excludedID, err := reservation.SegmentIDFromRaw(xtest.MustParseHexString(tc.excludeID)) - require.NoError(t, err) - sum := sumMaxBlockedBW(tc.rsvsFcn(), *excludedID) - require.Equal(t, tc.blockedBW, sum) - }) - } -} - -func TestAvailableBW(t *testing.T) { - req := newTestRequest(t, 1, 2, 5, 7) - - cases := map[string]struct { - availBW uint64 - delta float64 - req *segment.SetupReq - setupDB func(db *mock_backend.MockDB) - }{ - "empty DB": { - availBW: 1024, - delta: 1, - req: req, - setupDB: func(db *mock_backend.MockDB) { - db.EXPECT().GetSegmentRsvsFromIFPair(gomock.Any(), &req.Ingress, nil).Return( - nil, nil) - db.EXPECT().GetSegmentRsvsFromIFPair(gomock.Any(), nil, &req.Egress).Return( - nil, nil) - }, - }, - "this reservation in DB": { - // as the only reservation in DB has the same ID as the request, the availableBW - // function should return the same value as with an empty DB. - availBW: 1024, - delta: 1, - req: req, - setupDB: func(db *mock_backend.MockDB) { - db.EXPECT().GetSegmentRsvsFromIFPair(gomock.Any(), &req.Ingress, nil).Return( - []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 5, 5), - }, nil) - db.EXPECT().GetSegmentRsvsFromIFPair(gomock.Any(), nil, &req.Egress).Return( - []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 5, 5), - }, nil) - }, - }, - "other reservation in DB": { - availBW: 1024 - 64, - delta: 1, - req: req, - setupDB: func(db *mock_backend.MockDB) { - db.EXPECT().GetSegmentRsvsFromIFPair(gomock.Any(), &req.Ingress, nil).Return( - []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:2", "beefcafe", 1, 2, 5, 5, 5), - }, nil) - db.EXPECT().GetSegmentRsvsFromIFPair(gomock.Any(), nil, &req.Egress).Return( - []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:2", "beefcafe", 1, 2, 5, 5, 5), - }, nil) - }, - }, - "change delta": { - availBW: (1024 - 64) / 2, - delta: .5, - req: req, - setupDB: func(db *mock_backend.MockDB) { - db.EXPECT().GetSegmentRsvsFromIFPair(gomock.Any(), &req.Ingress, nil).Return( - []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:2", "beefcafe", 1, 2, 5, 5, 5), - }, nil) - db.EXPECT().GetSegmentRsvsFromIFPair(gomock.Any(), nil, &req.Egress).Return( - []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:2", "beefcafe", 1, 2, 5, 5, 5), - }, nil) - }, - }, - } - for name, tc := range cases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - adm, finish := newTestAdmitter(t) - defer finish() - - adm.Delta = tc.delta - ctx := context.Background() - db := adm.DB.(*mock_backend.MockDB) - tc.setupDB(db) - avail, err := adm.availableBW(ctx, tc.req) - require.NoError(t, err) - require.Equal(t, tc.availBW, avail) - }) - } -} - -func TestTubeRatio(t *testing.T) { - cases := map[string]struct { - tubeRatio float64 - req *segment.SetupReq - setupDB func(db *mock_backend.MockDB) - globalCapacity uint64 - interfaces []uint16 - }{ - "empty": { - tubeRatio: 1, - req: newTestRequest(t, 1, 2, 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{} - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - globalCapacity: 1024 * 1024, - interfaces: []uint16{1, 2, 3}, - }, - "one source, one ingress": { - tubeRatio: 1, - req: newTestRequest(t, 1, 2, 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "00000001", 1, 2, 5, 5, 5), - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - globalCapacity: 1024 * 1024, - interfaces: []uint16{1, 2, 3}, - }, - "one source, two ingress": { - tubeRatio: .5, - req: newTestRequest(t, 1, 2, 3, 3), // 64Kbps - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "00000001", 1, 2, 5, 3, 3), // 64Kbps - testNewRsv(t, "ff00:1:1", "00000002", 3, 2, 5, 5, 5), // 128Kbps - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - globalCapacity: 1024 * 1024, - interfaces: []uint16{1, 2, 3}, - }, - "two sources, request already present": { - tubeRatio: .5, - req: newTestRequest(t, 1, 2, 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 9, 9), // will be ignored - testNewRsv(t, "ff00:1:1", "00000002", 3, 2, 5, 5, 5), - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - globalCapacity: 1024 * 1024, - interfaces: []uint16{1, 2, 3}, - }, - "multiple sources, multiple ingress": { - tubeRatio: .75, - req: newTestRequest(t, 1, 2, 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "00000001", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:2", "00000001", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:1", "00000002", 3, 2, 5, 5, 5), - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - globalCapacity: 1024 * 1024, - interfaces: []uint16{1, 2, 3}, - }, - "exceeding ingress capacity": { - tubeRatio: 10. / 13., // 10 / (10 + 0 + 3) - req: newTestRequest(t, 1, 2, 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "00000001", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:2", "00000001", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:1", "00000002", 3, 2, 5, 5, 5), - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - globalCapacity: 10, - interfaces: []uint16{1, 2, 3}, - }, - "with many other irrelevant reservations": { - tubeRatio: .75, - req: newTestRequest(t, 1, 2, 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "00000001", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:2", "00000001", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:1", "00000002", 3, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:3", "00000001", 4, 5, 5, 9, 9), - testNewRsv(t, "ff00:1:3", "00000002", 4, 5, 5, 9, 9), - testNewRsv(t, "ff00:1:4", "00000001", 5, 4, 5, 9, 9), - testNewRsv(t, "ff00:1:4", "00000002", 5, 4, 5, 9, 9), - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - globalCapacity: 1024 * 1024, - interfaces: []uint16{1, 2, 3, 4, 5}, - }, - } - - for name, tc := range cases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - adm, finish := newTestAdmitter(t) - defer finish() - - adm.Capacities = &testCapacities{ - Cap: tc.globalCapacity, - Ifaces: tc.interfaces, - } - db := adm.DB.(*mock_backend.MockDB) - tc.setupDB(db) - - ctx := context.Background() - demPerSrc, err := adm.computeTempDemands(ctx, tc.req.Ingress, tc.req) - require.NoError(t, err) - ratio, err := adm.tubeRatio(ctx, tc.req, demPerSrc) - require.NoError(t, err) - require.Equal(t, tc.tubeRatio, ratio) - }) - } -} - -func TestLinkRatio(t *testing.T) { - cases := map[string]struct { - linkRatio float64 - req *segment.SetupReq - setupDB func(db *mock_backend.MockDB) - }{ - "empty": { - linkRatio: 1., - req: testAddAllocTrail(newTestRequest(t, 1, 2, 5, 5), 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{} - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - }, - "same request": { - linkRatio: 1., - req: testAddAllocTrail(newTestRequest(t, 1, 2, 5, 5), 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 5, 5), - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - }, - "same source": { - linkRatio: .5, - req: testAddAllocTrail(newTestRequest(t, 1, 2, 5, 5), 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "beefcafe", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:1", "00000001", 1, 2, 5, 5, 5), - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - }, - "different sources": { - linkRatio: 1. / 3., - req: testAddAllocTrail(newTestRequest(t, 1, 2, 5, 5), 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:2", "00000001", 1, 2, 5, 5, 5), - testNewRsv(t, "ff00:1:3", "00000001", 1, 2, 5, 5, 5), - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - }, - "different egress interface": { - linkRatio: .5, - req: testAddAllocTrail(newTestRequest(t, 1, 2, 5, 5), 5, 5), - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "00000001", 1, 3, 5, 5, 5), - // testNewRsv(t, "ff00:1:3", "00000001", 1, 2, 5, 5, 5), - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - }, - "smaller prevBW": { - linkRatio: 1. / 3., - req: testAddAllocTrail(newTestRequest(t, 1, 2, 5, 5), 3, 3), // 64 Kbps - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "00000001", 1, 2, 5, 5, 5), // 128 Kbps - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - }, - "bigger prevBW": { - linkRatio: 2. / 3., - req: testAddAllocTrail(newTestRequest(t, 1, 2, 5, 5), 7, 7), // 256 Kbps - setupDB: func(db *mock_backend.MockDB) { - rsvs := []*segment.Reservation{ - testNewRsv(t, "ff00:1:1", "00000001", 1, 2, 5, 5, 5), // 128 Kbps - } - db.EXPECT().GetAllSegmentRsvs(gomock.Any()).AnyTimes().Return(rsvs, nil) - }, - }, - } - - for name, tc := range cases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - adm, finish := newTestAdmitter(t) - defer finish() - - adm.Capacities = &testCapacities{ - Cap: 1024 * 1024, - Ifaces: []uint16{1, 2, 3}, - } - db := adm.DB.(*mock_backend.MockDB) - tc.setupDB(db) - - ctx := context.Background() - demsPerSrc, err := adm.computeTempDemands(ctx, tc.req.Ingress, tc.req) - require.NoError(t, err) - linkRatio, err := adm.linkRatio(ctx, tc.req, demsPerSrc) - require.NoError(t, err) - require.Equal(t, tc.linkRatio, linkRatio) - }) - } - -} - -type testCapacities struct { - Cap uint64 - Ifaces []uint16 -} - -var _ base.Capacities = (*testCapacities)(nil) - -func (c *testCapacities) IngressInterfaces() []uint16 { return c.Ifaces } -func (c *testCapacities) EgressInterfaces() []uint16 { return c.Ifaces } -func (c *testCapacities) Capacity(from, to uint16) uint64 { return c.Cap } -func (c *testCapacities) CapacityIngress(ingress uint16) uint64 { return c.Cap } -func (c *testCapacities) CapacityEgress(egress uint16) uint64 { return c.Cap } - -func newTestAdmitter(t *testing.T) (*StatelessAdmission, func()) { - mctlr := gomock.NewController(t) - - db := mock_backend.NewMockDB(mctlr) - return &StatelessAdmission{ - DB: db, - Capacities: &testCapacities{ - Cap: 1024, // 1MBps - Ifaces: []uint16{1, 2}, - }, - Delta: 1, - }, mctlr.Finish -} - -// newTestRequest creates a request ID ff00:1:1 beefcafe -func newTestRequest(t *testing.T, ingress, egress uint16, - minBW, maxBW reservation.BWCls) *segment.SetupReq { - - ID, err := reservation.SegmentIDFromRaw(xtest.MustParseHexString("ff0000010001beefcafe")) - require.NoError(t, err) - return &segment.SetupReq{ - Request: segment.Request{ - RequestMetadata: base.RequestMetadata{}, - ID: *ID, - Timestamp: util.SecsToTime(1), - Ingress: ingress, - Egress: egress, - }, - MinBW: minBW, - MaxBW: maxBW, - SplitCls: 2, - PathProps: reservation.StartLocal | reservation.EndLocal, - } -} - -func testNewRsv(t *testing.T, srcAS string, suffix string, ingress, egress uint16, - minBW, maxBW, allocBW reservation.BWCls) *segment.Reservation { - - ID, err := reservation.NewSegmentID(xtest.MustParseAS(srcAS), - xtest.MustParseHexString(suffix)) - require.NoError(t, err) - rsv := &segment.Reservation{ - ID: *ID, - Indices: segment.Indices{ - segment.Index{ - Idx: 10, - Expiration: util.SecsToTime(2), - MinBW: minBW, - MaxBW: maxBW, - AllocBW: allocBW, - }, - }, - Ingress: ingress, - Egress: egress, - PathType: reservation.UpPath, - PathEndProps: reservation.StartLocal | reservation.EndLocal | reservation.EndTransfer, - TrafficSplit: 2, - } - err = rsv.SetIndexConfirmed(10) - require.NoError(t, err) - err = rsv.SetIndexActive(10) - require.NoError(t, err) - return rsv -} - -// testAddAllocTrail adds an allocation trail to a reservation. The beads parameter represents -// the trail like: alloc0,max0,alloc1,max1,... -func testAddAllocTrail(req *segment.SetupReq, beads ...reservation.BWCls) *segment.SetupReq { - if len(beads)%2 != 0 { - panic("the beads must be even") - } - for i := 0; i < len(beads); i += 2 { - beads := reservation.AllocationBead{ - AllocBW: beads[i], - MaxBW: beads[i+1], - } - req.AllocTrail = append(req.AllocTrail, beads) - } - return req -} diff --git a/control/colibri/reservation/segment/export_test.go b/control/colibri/reservation/segment/export_test.go deleted file mode 100644 index 08b826129..000000000 --- a/control/colibri/reservation/segment/export_test.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 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 segment - -func (r *Reservation) GetActiveIndexForTesting() int { - return r.activeIndex -} -func (r *Reservation) SetActiveIndexForTesting(index int) { - r.activeIndex = index -} - -func (index *Index) SetStateForTesting(state IndexState) { - index.state = state -} diff --git a/control/colibri/reservation/segment/index.go b/control/colibri/reservation/segment/index.go deleted file mode 100644 index 02e52bf82..000000000 --- a/control/colibri/reservation/segment/index.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2020 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 segment - -import ( - "time" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" -) - -type IndexState uint8 - -// possible states of a segment reservation index. -const ( - IndexTemporary IndexState = iota - IndexPending // the index is confirmed, but not yet activated. - IndexActive -) - -// Index is a segment reservation index. -type Index struct { - Idx reservation.IndexNumber - Expiration time.Time - state IndexState - MinBW reservation.BWCls - MaxBW reservation.BWCls - AllocBW reservation.BWCls - Token *reservation.Token -} - -// NewIndex creates a new Index without yet linking it to any reservation. -func NewIndex(idx reservation.IndexNumber, expiration time.Time, state IndexState, - minBW, maxBW, allocBW reservation.BWCls, token *reservation.Token) *Index { - return &Index{ - Idx: idx, - Expiration: expiration, - state: state, - MinBW: minBW, - MaxBW: maxBW, - AllocBW: allocBW, - Token: token, - } -} - -// State returns the read-only state. -func (index *Index) State() IndexState { - return index.state -} - -// Indices is a collection of Index that implements IndicesInterface. -type Indices []Index - -var _ base.IndicesInterface = (*Indices)(nil) - -func (idxs Indices) Len() int { return len(idxs) } -func (idxs Indices) GetIndexNumber(i int) reservation.IndexNumber { return idxs[i].Idx } -func (idxs Indices) GetExpiration(i int) time.Time { return idxs[i].Expiration } -func (idxs Indices) GetAllocBW(i int) reservation.BWCls { return idxs[i].AllocBW } -func (idxs Indices) GetToken(i int) *reservation.Token { return idxs[i].Token } -func (idxs Indices) Rotate(i int) base.IndicesInterface { - return append(idxs[i:], idxs[:i]...) -} diff --git a/control/colibri/reservation/segment/path.go b/control/colibri/reservation/segment/path.go deleted file mode 100644 index a2eb8afec..000000000 --- a/control/colibri/reservation/segment/path.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2020 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 segment - -import ( - "encoding/binary" - "fmt" - "io" - "strings" - - "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/private/serrors" -) - -// ReservationTransparentPath represents a reservation path, in the reservation order. -// This path is seen only in the source of a segment reservation. -// TODO(juagargi) there exists a ColibriPath that could be used instead, if we only -// need equality. If we need to know the IDs of the transit ASes, it won't be possible. -type ReservationTransparentPath []PathStepWithIA - -var _ io.Reader = (*ReservationTransparentPath)(nil) - -// NewPathFromRaw constructs a new Path from the byte representation. -func NewPathFromRaw(buff []byte) (ReservationTransparentPath, error) { - if len(buff)%PathStepWithIALen != 0 { - return nil, serrors.New("buffer input is not a multiple of a path step", "len", len(buff)) - } - steps := len(buff) / PathStepWithIALen - p := make(ReservationTransparentPath, steps) - for i := 0; i < steps; i++ { - offset := i * PathStepWithIALen - p[i].Ingress = binary.BigEndian.Uint16(buff[offset:]) - p[i].Egress = binary.BigEndian.Uint16(buff[offset+2:]) - p[i].IA = addr.IA(binary.BigEndian.Uint64(buff[offset+4:])) - } - return p, nil -} - -// Validate returns an error if there is invalid data. -func (p ReservationTransparentPath) Validate() error { - if len(p) < 2 { - return serrors.New("invalid path length", "len", len(p)) - } - if p[0].Ingress != 0 { - return serrors.New("wrong ingress interface for source", "ingress", p[0].Ingress) - } - if p[len(p)-1].Egress != 0 { - return serrors.New("wrong egress interface for destination", - "egress ID", p[len(p)-1].Ingress) - } - return nil -} - -// Equal returns true if both ReservationTransparentPath contain the same values. -func (p ReservationTransparentPath) Equal(o ReservationTransparentPath) bool { - if len(p) != len(o) { - return false - } - for i := 0; i < len(p); i++ { - if p[i] != o[i] { - return false - } - } - return true -} - -// GetSrcIA returns the source IA in the path or a zero IA if the path is nil (it's not the -// source AS of the reservation and has no access to the path of the reservation). -// If the Path is not nil, it assumes is valid, i.e. it has at least length 2. -func (p ReservationTransparentPath) GetSrcIA() addr.IA { - if len(p) == 0 { - return 0 - } - return p[0].IA -} - -// GetDstIA returns the source IA in the path or a zero IA if the path is nil (it's not the -// source AS of the reservation and has no access to the path of the reservation). -// If the path is not nil, it assumes is valid, i.e. it has at least length 2. -func (p ReservationTransparentPath) GetDstIA() addr.IA { - if len(p) == 0 { - return 0 - } - return p[len(p)-1].IA -} - -// Len returns the length of this path in bytes, when serialized. -func (p ReservationTransparentPath) Len() int { - if len(p) == 0 { - return 0 - } - return len(p) * PathStepWithIALen -} - -func (p ReservationTransparentPath) Read(buff []byte) (int, error) { - if len(p) == 0 { - return 0, nil - } - if len(buff) < p.Len() { - return 0, serrors.New("buffer too small", "min_size", p.Len(), "actual_size", len(buff)) - } - for i, s := range p { - offset := i * PathStepWithIALen - binary.BigEndian.PutUint16(buff[offset:], s.Ingress) - binary.BigEndian.PutUint16(buff[offset+2:], s.Egress) - binary.BigEndian.PutUint64(buff[offset+4:], uint64(s.IA)) - } - return p.Len(), nil -} - -// ToRaw returns a buffer representing this ReservationTransparentPath. -func (p ReservationTransparentPath) ToRaw() []byte { - if len(p) == 0 { - return nil - } - buff := make([]byte, p.Len()) - _, _ = p.Read(buff) - return buff -} - -func (p ReservationTransparentPath) String() string { - strs := make([]string, len(p)) - for i, s := range p { - strs[i] = s.String() - } - return strings.Join(strs, ">") -} - -// PathStep is one hop of the ReservationTransparentPath. -// For a source AS Ingress will be invalid. Conversely for dst. -type PathStep struct { - Ingress uint16 - Egress uint16 -} - -// PathStepWithIA is a step in a reservation path as seen from the source AS. -type PathStepWithIA struct { - PathStep - IA addr.IA -} - -// PathStepWithIALen amounts for Ingress+Egress+IA. -const PathStepWithIALen = 2 + 2 + 8 - -func (s *PathStepWithIA) String() string { - return fmt.Sprintf("%d %s %d", s.Ingress, s.IA.String(), s.Egress) -} diff --git a/control/colibri/reservation/segment/path_test.go b/control/colibri/reservation/segment/path_test.go deleted file mode 100644 index cbfa73534..000000000 --- a/control/colibri/reservation/segment/path_test.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2020 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 segment_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/control/colibri/reservation/segmenttest" - "github.com/scionproto/scion/pkg/private/xtest" -) - -func TestValidatePath(t *testing.T) { - tc := map[string]struct { - Path segment.ReservationTransparentPath - IsValid bool - }{ - "src-dst": { - Path: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0), - IsValid: true, - }, - "invalid dst": { - Path: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 2), - IsValid: false, - }, - "invalid src": { - Path: segmenttest.NewPathFromComponents(2, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0), - IsValid: false, - }, - } - for name, tc := range tc { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - err := tc.Path.Validate() - if tc.IsValid { - require.NoError(t, err) - } else { - require.Error(t, err) - } - }) - } -} - -func TestEqualPath(t *testing.T) { - tc := map[string]struct { - Path1 segment.ReservationTransparentPath - Path2 segment.ReservationTransparentPath - IsEqual bool - }{ - "eq1": { - Path1: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0), - Path2: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0), - IsEqual: true, - }, - "eq2": { - Path1: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 2, "1-ff00:1:10", 3, - 1, "1-ff00:0:2", 0), - Path2: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 2, "1-ff00:1:10", 3, - 1, "1-ff00:0:2", 0), - IsEqual: true, - }, - "eq3": { - Path1: nil, - Path2: nil, - IsEqual: true, - }, - "eq4": { - Path1: nil, - Path2: make(segment.ReservationTransparentPath, 0), - IsEqual: true, - }, - "neq1": { - Path1: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0), - Path2: segmenttest.NewPathFromComponents(1, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0), - IsEqual: false, - }, - "neq2": { - Path1: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0), - Path2: segmenttest.NewPathFromComponents(0, "1-ff00:0:3", 1, 1, "1-ff00:0:2", 0), - IsEqual: false, - }, - "neq3": { - Path1: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0), - Path2: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 2, 1, "1-ff00:0:2", 0), - IsEqual: false, - }, - "neq4": { - Path1: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 2, "1-ff00:1:10", 3, - 1, "1-ff00:0:2", 0), - Path2: segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 2, "1-ff00:1:10", 3), - IsEqual: false, - }, - } - for name, tc := range tc { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - eq := tc.Path1.Equal(tc.Path2) - require.Equal(t, tc.IsEqual, eq) - }) - } -} - -func TestGetIAs(t *testing.T) { - p := segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0) - require.Equal(t, xtest.MustParseIA("1-ff00:0:1"), p.GetSrcIA()) - require.Equal(t, xtest.MustParseIA("1-ff00:0:2"), p.GetDstIA()) - p = nil - require.Equal(t, xtest.MustParseIA("0-0"), p.GetSrcIA()) - require.Equal(t, xtest.MustParseIA("0-0"), p.GetDstIA()) - p = make(segment.ReservationTransparentPath, 0) - require.Equal(t, xtest.MustParseIA("0-0"), p.GetSrcIA()) - require.Equal(t, xtest.MustParseIA("0-0"), p.GetDstIA()) -} - -func TestPathLen(t *testing.T) { - p := segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0) - require.Equal(t, 2*12, p.Len()) - p = segment.ReservationTransparentPath{} - require.Equal(t, 0, p.Len()) - p = nil - require.Equal(t, 0, p.Len()) - p = make(segment.ReservationTransparentPath, 0) - require.Equal(t, 0, p.Len()) -} - -func TestToFromBinary(t *testing.T) { - p := segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0) - var buff []byte - _, err := p.Read(buff) - require.Error(t, err) - _, err = p.Read(buff) - require.Error(t, err) - buff = make([]byte, 2*12) - c, err := p.Read(buff) - require.NoError(t, err) - require.Equal(t, 2*12, c) - - anotherP, err := segment.NewPathFromRaw(buff) - require.NoError(t, err) - require.Equal(t, p, anotherP) - - anotherBuff := p.ToRaw() - require.Equal(t, buff, anotherBuff) - // wrong buffer - buff = buff[:len(buff)-1] - _, err = segment.NewPathFromRaw(buff) - require.Error(t, err) - // empty and nil buffer - p, err = segment.NewPathFromRaw(nil) - require.NoError(t, err) - require.Empty(t, p) - p, err = segment.NewPathFromRaw([]byte{}) - require.NoError(t, err) - require.Empty(t, p) - // empty and nil path - p = nil - require.Empty(t, p.ToRaw()) - p = make(segment.ReservationTransparentPath, 0) - require.Empty(t, p.ToRaw()) -} - -func TestString(t *testing.T) { - p := segmenttest.NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0) - require.Equal(t, "0 1-ff00:0:1 1>1 1-ff00:0:2 0", p.String()) -} diff --git a/control/colibri/reservation/segment/request.go b/control/colibri/reservation/segment/request.go deleted file mode 100644 index a3a132d99..000000000 --- a/control/colibri/reservation/segment/request.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2020 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 segment - -import ( - "time" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" -) - -// Request is the base struct for any type of COLIBRI segment request. -// It contains a reference to the reservation it requests, or nil if not yet created. -type Request struct { - base.RequestMetadata // information about the request (forwarding path) - ID reservation.SegmentID // the ID this request refers to - Index reservation.IndexNumber // the index this request refers to - Timestamp time.Time // the mandatory timestamp - Ingress uint16 // the interface the traffic uses to enter the AS - Egress uint16 // the interface the traffic uses to leave the AS - Reservation *Reservation // nil if no reservation yet -} - -// NewRequest constructs the segment Request type. -func NewRequest(ts time.Time, id *reservation.SegmentID, idx reservation.IndexNumber, - path base.ColibriPath) (*Request, error) { - - metadata, err := base.NewRequestMetadata(path) - if err != nil { - return nil, serrors.WrapStr("new segment request", err) - } - ingressIFID, egressIFID := path.IngressEgressIFIDs() - if id == nil { - return nil, serrors.New("new segment request with nil ID") - } - return &Request{ - RequestMetadata: *metadata, - Timestamp: ts, - ID: *id, - Index: idx, - Ingress: ingressIFID, - Egress: egressIFID, - }, nil -} - -// SetupReq is a segment reservation setup request. -// This same type is used for renewal of the segment reservation. -type SetupReq struct { - Request - InfoField reservation.InfoField - MinBW reservation.BWCls - MaxBW reservation.BWCls - SplitCls reservation.SplitCls - PathProps reservation.PathEndProps - AllocTrail reservation.AllocationBeads -} - -// SetupTelesReq represents a telescopic segment setup. -type SetupTelesReq struct { - SetupReq - BaseID reservation.SegmentID -} - -// TeardownReq requests the AS to remove a given index from the DB. If this is the last index -// in the reservation, the reservation will be completely removed. -type TeardownReq struct { - Request -} - -// IndexConfirmationReq is used to change the state on an index (e.g. from temporary to pending). -type IndexConfirmationReq struct { - Request - State IndexState -} - -// CleanupReq is used to clean an index. -type CleanupReq struct { - Request -} diff --git a/control/colibri/reservation/segment/reservation.go b/control/colibri/reservation/segment/reservation.go deleted file mode 100644 index 0c9faad4d..000000000 --- a/control/colibri/reservation/segment/reservation.go +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2020 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 segment - -import ( - "time" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" -) - -// Reservation represents a segment reservation. -type Reservation struct { - ID reservation.SegmentID - Indices Indices // existing indices in this reservation - activeIndex int // -1 <= activeIndex < len(Indices) - Ingress uint16 // igress interface ID: reservation packets enter - Egress uint16 // egress interface ID: reservation packets leave - Path ReservationTransparentPath // empty if not at the source of the reservation - PathType reservation.PathType // the type of path (up,core,down) - PathEndProps reservation.PathEndProps // the properties for stitching and start/end - TrafficSplit reservation.SplitCls // the traffic split between control and data planes -} - -func NewReservation() *Reservation { - return &Reservation{ - activeIndex: -1, - } -} - -// Validate will return an error for invalid values. -func (r *Reservation) Validate() error { - if r.ID.ASID == 0 { - return serrors.New("Reservation ID not set") - } - if err := base.ValidateIndices(r.Indices); err != nil { - return err - } - if r.activeIndex < -1 || r.activeIndex > 0 || r.activeIndex >= len(r.Indices) { - // when we activate an index all previous indices are removed. - // Thus activeIndex can only be -1 or 0 - return serrors.New("invalid active index", "active_index", r.activeIndex) - } - activeIndex := -1 - for i, index := range r.Indices { - if index.State() == IndexActive { - if activeIndex != -1 { - return serrors.New("more than one active index", - "first_active", r.Indices[activeIndex].Idx, "another_active", index.Idx) - } - activeIndex = i - } - } - var err error - if r.Path != nil { - if r.Ingress != 0 { - return serrors.New("reservation starts in this AS but ingress interface is not zero", - "ingress_if", r.Ingress) - } - err = r.Path.Validate() - } else if r.Ingress == 0 { - return serrors.New("reservation does not start in this AS but ingress interface is zero") - } - if err != nil { - return serrors.WrapStr("validating reservation, path failed", err) - } - err = r.PathEndProps.Validate() - if err != nil { - return serrors.WrapStr("validating reservation, end properties failed", err) - } - return nil -} - -// ActiveIndex returns the currently active Index for this reservation, or nil if none. -func (r *Reservation) ActiveIndex() *Index { - if r.activeIndex == -1 { - return nil - } - return &r.Indices[r.activeIndex] -} - -// NewIndexAtSource creates a new index. The associated token is created from the arguments, and -// automatically linked to the index. This function should be called only from the -// AS originating the reservation. -// The expiration times must always be greater or equal than those in previous indices. -func (r *Reservation) NewIndexAtSource(expTime time.Time, minBW, maxBW, allocBW reservation.BWCls, - rlc reservation.RLC, pathType reservation.PathType) (reservation.IndexNumber, error) { - - idx := reservation.IndexNumber(0) - if len(r.Indices) > 0 { - idx = r.Indices[len(r.Indices)-1].Idx.Add(1) - } - tok := &reservation.Token{ - InfoField: reservation.InfoField{ - Idx: idx, - ExpirationTick: reservation.TickFromTime(expTime), - BWCls: allocBW, - RLC: rlc, - PathType: pathType, - }, - } - index := NewIndex(idx, expTime, IndexTemporary, minBW, maxBW, allocBW, tok) - return r.addIndex(index) -} - -// NewIndexFromToken creates a new index. The token argument is used to populate several -// fields of the index. The token is not stored (on-path ASes don't need the token). -// This function should be called from an AS that is on the reservation path -// but not the originating one. -func (r *Reservation) NewIndexFromToken(tok *reservation.Token, minBW, maxBW reservation.BWCls) ( - reservation.IndexNumber, error) { - - if tok == nil { - return 0, serrors.New("token is nil") - } - index := NewIndex(tok.Idx, tok.ExpirationTick.ToTime(), IndexTemporary, minBW, maxBW, - tok.BWCls, nil) - return r.addIndex(index) -} - -func (r *Reservation) addIndex(index *Index) (reservation.IndexNumber, error) { - newIndices := make(Indices, len(r.Indices)+1) - copy(newIndices, r.Indices) - newIndices[len(newIndices)-1] = *index - if err := base.ValidateIndices(newIndices); err != nil { - return 0, err - } - r.Indices = newIndices - return index.Idx, nil -} - -// Index finds the Index with that IndexNumber and returns a pointer to it. -func (r *Reservation) Index(idx reservation.IndexNumber) *Index { - sliceIndex, err := base.FindIndex(r.Indices, idx) - if err != nil { - return nil - } - return &r.Indices[sliceIndex] -} - -// SetIndexConfirmed sets the index as IndexPending (confirmed but not active). If the requested -// index has state active, it will emit an error. -func (r *Reservation) SetIndexConfirmed(idx reservation.IndexNumber) error { - sliceIndex, err := base.FindIndex(r.Indices, idx) - if err != nil { - return err - } - if r.Indices[sliceIndex].state == IndexActive { - return serrors.New("cannot confirm an already active index", "index_number", idx) - } - r.Indices[sliceIndex].state = IndexPending - return nil -} - -// SetIndexActive sets the index as active. If the reservation had already an active state, -// it will remove all previous indices. -func (r *Reservation) SetIndexActive(idx reservation.IndexNumber) error { - sliceIndex, err := base.FindIndex(r.Indices, idx) - if err != nil { - return err - } - if r.activeIndex == sliceIndex { - return nil // already active - } - // valid states are Pending (nominal) and Active (reconstructing from DB needs this) - if r.Indices[sliceIndex].state != IndexPending && r.Indices[sliceIndex].state != IndexActive { - return serrors.New("attempt to activate a non confirmed index", "index_number", idx, - "state", r.Indices[sliceIndex].state) - } - if r.activeIndex > -1 { - if r.activeIndex > sliceIndex { - return serrors.New("activating a past index", - "last active", r.Indices[r.activeIndex].Idx, "current", idx) - } - } - // remove indices [lastActive,currActive) so that currActive is at position 0 - r.Indices = r.Indices[sliceIndex:] - r.activeIndex = 0 - r.Indices[0].state = IndexActive - return nil -} - -// RemoveIndex removes all indices from the beginning until this one, inclusive. -func (r *Reservation) RemoveIndex(idx reservation.IndexNumber) error { - sliceIndex, err := base.FindIndex(r.Indices, idx) - if err != nil { - return err - } - r.Indices = r.Indices[sliceIndex+1:] - r.activeIndex -= sliceIndex - if r.activeIndex < -1 { - r.activeIndex = -1 - } - return nil -} - -// MaxBlockedBW returns the maximum bandwidth blocked by this reservation, which is -// the same as the maximum allocated bandwidth indicated by its indices. -func (r *Reservation) MaxBlockedBW() uint64 { - if len(r.Indices) == 0 { - return 0 - } - var max reservation.BWCls - for _, idx := range r.Indices { - max = reservation.MaxBWCls(max, idx.AllocBW) - } - return max.ToKbps() -} - -// MaxRequestedBW returns the maximum bandwidth requested by this reservation. -func (r *Reservation) MaxRequestedBW() uint64 { - if len(r.Indices) == 0 { - return 0 - } - var max reservation.BWCls - for _, idx := range r.Indices { - max = reservation.MaxBWCls(max, idx.MaxBW) - } - return max.ToKbps() -} diff --git a/control/colibri/reservation/segment/reservation_test.go b/control/colibri/reservation/segment/reservation_test.go deleted file mode 100644 index 22c907f3b..000000000 --- a/control/colibri/reservation/segment/reservation_test.go +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2020 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 segment_test - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/control/colibri/reservation/segmenttest" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/util" -) - -func TestNewIndexAtSource(t *testing.T) { - r := segmenttest.NewReservation() - require.Len(t, r.Indices, 0) - expTime := util.SecsToTime(1) - idx, err := r.NewIndexAtSource(expTime, 1, 3, 2, 5, reservation.CorePath) - require.NoError(t, err) - require.Len(t, r.Indices, 1) - require.Equal(t, reservation.IndexNumber(0), idx) - require.Equal(t, idx, r.Indices[0].Idx) - require.Equal(t, expTime, r.Indices[0].Expiration) - require.Equal(t, segment.IndexTemporary, r.Indices[0].State()) - require.Equal(t, reservation.BWCls(1), r.Indices[0].MinBW) - require.Equal(t, reservation.BWCls(3), r.Indices[0].MaxBW) - require.Equal(t, reservation.BWCls(2), r.Indices[0].AllocBW) - require.NotNil(t, r.Indices[0].Token) - tok := &reservation.Token{ - InfoField: reservation.InfoField{ - ExpirationTick: reservation.TickFromTime(expTime), - BWCls: 2, - RLC: 5, - Idx: idx, - PathType: reservation.CorePath, - }, - } - require.Equal(t, tok, r.Indices[0].Token) - // add a second index - idx, err = r.NewIndexAtSource(expTime, 1, 3, 2, 5, reservation.CorePath) - require.NoError(t, err) - require.Len(t, r.Indices, 2) - require.Equal(t, reservation.IndexNumber(1), idx) - require.Equal(t, idx, r.Indices[1].Idx) - // remove first index and add another one - r.Indices = r.Indices[1:] - idx, err = r.NewIndexAtSource(expTime, 1, 3, 2, 5, reservation.CorePath) - require.NoError(t, err) - require.Len(t, r.Indices, 2) - require.Equal(t, reservation.IndexNumber(2), idx) - require.Equal(t, idx, r.Indices[1].Idx) -} - -func TestNewIndexFromToken(t *testing.T) { - r := segmenttest.NewReservation() - require.Len(t, r.Indices, 0) - expTime := time.Unix(1, 0) - tok := &reservation.Token{ - InfoField: reservation.InfoField{ - ExpirationTick: reservation.TickFromTime(expTime), - BWCls: 2, - RLC: 5, - Idx: reservation.IndexNumber(6), - PathType: reservation.CorePath, - }, - } - idx, err := r.NewIndexFromToken(tok, 1, 3) - require.NoError(t, err) - require.Equal(t, tok.Idx, idx) - require.Equal(t, tok.ExpirationTick.ToTime(), r.Indices[0].Expiration) - require.Equal(t, segment.IndexTemporary, r.Indices[0].State()) - require.Equal(t, reservation.BWCls(1), r.Indices[0].MinBW) - require.Equal(t, reservation.BWCls(3), r.Indices[0].MaxBW) - require.Equal(t, tok.BWCls, r.Indices[0].AllocBW) - require.Nil(t, r.Indices[0].Token) - // nil token - _, err = r.NewIndexFromToken(nil, 0, 0) - require.Error(t, err) -} - -func TestReservationValidate(t *testing.T) { - r := segmenttest.NewReservation() - err := r.Validate() - require.NoError(t, err) - // wrong path - r.Path = segment.ReservationTransparentPath{} - err = r.Validate() - require.Error(t, err) - // more than one active index - expTime := util.SecsToTime(1) - r = segmenttest.NewReservation() - r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - require.Len(t, r.Indices, 2) - r.Indices[0].SetStateForTesting(segment.IndexActive) - r.Indices[1].SetStateForTesting(segment.IndexActive) - err = r.Validate() - require.Error(t, err) - // ID not set - r = segmenttest.NewReservation() - r.ID = reservation.SegmentID{} - err = r.Validate() - require.Error(t, err) - // starts in this AS but ingress nonzero - r = segmenttest.NewReservation() - r.Ingress = 1 - err = r.Validate() - require.Error(t, err) - // Does not start in this AS but ingress empty - r = segmenttest.NewReservation() - r.Path = nil - err = r.Validate() - require.Error(t, err) -} - -func TestIndex(t *testing.T) { - r := segmenttest.NewReservation() - expTime := util.SecsToTime(1) - r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - idx, _ := r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - require.Len(t, r.Indices, 3) - index := r.Index(idx) - require.Equal(t, &r.Indices[1], index) - index = r.Index(reservation.IndexNumber(4)) - require.Nil(t, index) - r.SetIndexConfirmed(idx) - r.SetIndexActive(idx) - index = r.Index(idx) - require.Equal(t, &r.Indices[0], index) -} - -func TestSetIndexConfirmed(t *testing.T) { - r := segmenttest.NewReservation() - expTime := util.SecsToTime(1) - id, _ := r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - require.Equal(t, segment.IndexTemporary, r.Indices[0].State()) - err := r.SetIndexConfirmed(id) - require.NoError(t, err) - require.Equal(t, segment.IndexPending, r.Indices[0].State()) - - // confirm already confirmed - err = r.SetIndexConfirmed(id) - require.NoError(t, err) - require.Equal(t, segment.IndexPending, r.Indices[0].State()) -} - -func TestSetIndexActive(t *testing.T) { - r := segmenttest.NewReservation() - expTime := util.SecsToTime(1) - - // index not confirmed - idx, _ := r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - err := r.SetIndexActive(idx) - require.Error(t, err) - - // normal activation - r.SetIndexConfirmed(idx) - err = r.SetIndexActive(idx) - require.NoError(t, err) - require.Equal(t, segment.IndexActive, r.Indices[0].State()) - require.Equal(t, 0, r.GetActiveIndexForTesting()) - - // already active - err = r.SetIndexActive(idx) - require.NoError(t, err) - - // remove previous indices - r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - idx, _ = r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - require.Len(t, r.Indices, 3) - require.Equal(t, 0, r.GetActiveIndexForTesting()) - r.SetIndexConfirmed(idx) - err = r.SetIndexActive(idx) - require.NoError(t, err) - require.Len(t, r.Indices, 1) - require.Equal(t, 0, r.GetActiveIndexForTesting()) - require.True(t, r.Indices[0].Idx == idx) -} - -func TestRemoveIndex(t *testing.T) { - r := segmenttest.NewReservation() - expTime := util.SecsToTime(1) - idx, _ := r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - err := r.RemoveIndex(idx) - require.NoError(t, err) - require.Len(t, r.Indices, 0) - - // remove second index - idx, _ = r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - idx2, _ := r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - err = r.RemoveIndex(idx) - require.NoError(t, err) - require.Len(t, r.Indices, 1) - require.True(t, r.Indices[0].Idx == idx2) - err = r.Validate() - require.NoError(t, err) - - // remove also removes older indices - expTime = expTime.Add(time.Second) - r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - idx, _ = r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - idx2, _ = r.NewIndexAtSource(expTime, 0, 0, 0, 0, reservation.CorePath) - require.Len(t, r.Indices, 4) - err = r.RemoveIndex(idx) - require.NoError(t, err) - require.Len(t, r.Indices, 1) - require.True(t, r.Indices[0].Idx == idx2) - err = r.Validate() - require.NoError(t, err) -} - -func TestMaxBlockedBW(t *testing.T) { - r := segmenttest.NewReservation() - r.Indices = r.Indices[:0] - require.Equal(t, uint64(0), r.MaxBlockedBW()) - r.NewIndexAtSource(util.SecsToTime(1), 1, 1, 1, 1, reservation.CorePath) - require.Equal(t, reservation.BWCls(1).ToKbps(), r.MaxBlockedBW()) - r.NewIndexAtSource(util.SecsToTime(1), 1, 1, 1, 1, reservation.CorePath) - require.Equal(t, reservation.BWCls(1).ToKbps(), r.MaxBlockedBW()) - r.Indices[0].AllocBW = 11 - require.Equal(t, reservation.BWCls(11).ToKbps(), r.MaxBlockedBW()) -} diff --git a/control/colibri/reservation/segment/response.go b/control/colibri/reservation/segment/response.go deleted file mode 100644 index 809f62906..000000000 --- a/control/colibri/reservation/segment/response.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2020 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 segment - -import ( - "time" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" -) - -// Response is the base struct for any type of COLIBRI segment response. -type Response struct { - base.RequestMetadata // information about the request (forwarding path) - ID reservation.SegmentID // the ID this request refers to - Index reservation.IndexNumber // the index this request refers to - Accepted bool // success or failure type of response - FailedHop uint8 // if accepted is false, the AS that failed it -} - -var _ base.MessageWithPath = (*Response)(nil) - -// NewResponse contructs the segment Response type. -func NewResponse(ts time.Time, id *reservation.SegmentID, idx reservation.IndexNumber, - path base.ColibriPath, accepted bool, failedHop uint8) (*Response, error) { - - metadata, err := base.NewRequestMetadata(path) - if err != nil { - return nil, serrors.WrapStr("new segment request", err) - } - if id == nil { - return nil, serrors.New("new segment response with nil ID") - } - return &Response{ - RequestMetadata: *metadata, - ID: *id, - Index: idx, - Accepted: accepted, - FailedHop: failedHop, - }, nil -} - -// ResponseSetupSuccess is the response to a success setup. It's sent on the reverse direction. -type ResponseSetupSuccess struct { - Response - Token reservation.Token -} - -// ResponseSetupFailure is the response to a failed setup. It's sent on the reverse direction. -type ResponseSetupFailure struct { - Response - FailedSetup *SetupReq -} - -// ResponseTeardownSuccess is sent by the last AS in the reverse path. -type ResponseTeardownSuccess struct { - Response -} - -// ResponseTeardownFailure is sent in the reverse path. -type ResponseTeardownFailure struct { - Response - ErrorCode uint8 -} - -// ResponseIndexConfirmationSuccess is a successful index confirmation. The target state is -// echoed in the response. -type ResponseIndexConfirmationSuccess struct { - Response - State IndexState -} - -// ResponseIndexConfirmationFailure is a failed index confirmation. -type ResponseIndexConfirmationFailure struct { - Response - ErrorCode uint8 -} - -// ResponseCleanupSuccess is a response to a successful cleanup request. -type ResponseCleanupSuccess struct { - Response -} - -// ResponseCleanupFailure is a failed index cleanup. -type ResponseCleanupFailure struct { - Response - ErrorCode uint8 -} diff --git a/control/colibri/reservation/segmenttest/BUILD.bazel b/control/colibri/reservation/segmenttest/BUILD.bazel deleted file mode 100644 index 9fb8c4629..000000000 --- a/control/colibri/reservation/segmenttest/BUILD.bazel +++ /dev/null @@ -1,13 +0,0 @@ -load("//tools/lint:go.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["common.go"], - importpath = "github.com/scionproto/scion/control/colibri/reservation/segmenttest", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation/segment:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/xtest:go_default_library", - ], -) diff --git a/control/colibri/reservation/segmenttest/common.go b/control/colibri/reservation/segmenttest/common.go deleted file mode 100644 index 75409d74d..000000000 --- a/control/colibri/reservation/segmenttest/common.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2020 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 segmenttest - -import ( - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/xtest" -) - -func NewPathFromComponents(chain ...interface{}) segment.ReservationTransparentPath { - if len(chain)%3 != 0 { - panic("wrong number of arguments") - } - p := segment.ReservationTransparentPath{} - for i := 0; i < len(chain); i += 3 { - p = append(p, segment.PathStepWithIA{ - PathStep: segment.PathStep{ - Ingress: uint16(chain[i].(int)), - Egress: uint16(chain[i+2].(int)), - }, - IA: xtest.MustParseIA(chain[i+1].(string)), - }) - } - return p -} - -func NewReservation() *segment.Reservation { - segID, err := reservation.NewSegmentID(xtest.MustParseAS("ff00:0:1"), - xtest.MustParseHexString("beefcafe")) - if err != nil { - panic(err) - } - r := segment.NewReservation() - r.ID = *segID - r.Path = NewPathFromComponents(0, "1-ff00:0:1", 1, 1, "1-ff00:0:2", 0) - return r -} diff --git a/control/colibri/reservation/sqlite/BUILD.bazel b/control/colibri/reservation/sqlite/BUILD.bazel deleted file mode 100644 index a9cef9dc8..000000000 --- a/control/colibri/reservation/sqlite/BUILD.bazel +++ /dev/null @@ -1,38 +0,0 @@ -load("//tools/lint:go.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "db.go", - "schema.go", - ], - importpath = "github.com/scionproto/scion/control/colibri/reservation/sqlite", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation:go_default_library", - "//control/colibri/reservation/e2e:go_default_library", - "//control/colibri/reservation/segment:go_default_library", - "//control/colibri/reservationstorage/backend:go_default_library", - "//pkg/addr:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/serrors:go_default_library", - "//pkg/private/util:go_default_library", - "//private/storage/db:go_default_library", - "@com_github_mattn_go_sqlite3//:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["db_test.go"], - embed = [":go_default_library"], - deps = [ - "//control/colibri/reservation/reservationdbtest:go_default_library", - "//control/colibri/reservation/segment:go_default_library", - "//pkg/addr:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/xtest:go_default_library", - "@com_github_mattn_go_sqlite3//:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) diff --git a/control/colibri/reservation/sqlite/db.go b/control/colibri/reservation/sqlite/db.go deleted file mode 100644 index 6af562de2..000000000 --- a/control/colibri/reservation/sqlite/db.go +++ /dev/null @@ -1,809 +0,0 @@ -// Copyright 2020 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 sqlite - -import ( - "context" - "database/sql" - "encoding/binary" - "encoding/hex" - "fmt" - "strings" - "sync" - "time" - - "github.com/mattn/go-sqlite3" - _ "github.com/mattn/go-sqlite3" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/control/colibri/reservation/e2e" - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/control/colibri/reservationstorage/backend" - "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" - "github.com/scionproto/scion/pkg/private/util" - "github.com/scionproto/scion/private/storage/db" -) - -type Backend struct { - *executor - db *sql.DB -} - -var _ backend.DB = (*Backend)(nil) - -// New returns a new SQLite backend opening a database at the given path. If -// no database exists a new database is be created. If the schema version of the -// stored database is different from the one in schema.go, an error is returned. -func New(path string) (*Backend, error) { - db, err := db.NewSqlite(path, Schema, SchemaVersion) - if err != nil { - return nil, err - } - return &Backend{ - executor: &executor{ - db: db, - }, - db: db, - }, nil -} - -// SetMaxOpenConns sets the maximum number of open connections. -func (b *Backend) SetMaxOpenConns(maxOpenConns int) { - b.db.SetMaxOpenConns(maxOpenConns) -} - -// SetMaxIdleConns sets the maximum number of idle connections. -func (b *Backend) SetMaxIdleConns(maxIdleConns int) { - b.db.SetMaxIdleConns(maxIdleConns) -} - -// BeginTransaction begins a transaction on the database. -func (b *Backend) BeginTransaction(ctx context.Context, opts *sql.TxOptions) ( - backend.Transaction, error) { - - b.Lock() - defer b.Unlock() - tx, err := b.db.BeginTx(ctx, opts) - if err != nil { - return nil, db.NewTxError("create tx", err) - } - return &transaction{ - executor: &executor{ - db: tx, - }, - tx: tx, - }, nil -} - -// Close closes the databse. -func (b *Backend) Close() error { - return b.db.Close() -} - -type transaction struct { - *executor - tx *sql.Tx -} - -var _ backend.Transaction = (*transaction)(nil) - -func (t *transaction) Commit() error { - t.Lock() - defer t.Unlock() - return t.tx.Commit() -} - -func (t *transaction) Rollback() error { - t.Lock() - defer t.Unlock() - return t.tx.Rollback() -} - -type executor struct { - sync.RWMutex - db db.Sqler -} - -func (x *executor) GetSegmentRsvFromID(ctx context.Context, ID *reservation.SegmentID) ( - *segment.Reservation, error) { - - params := []interface{}{ - ID.ASID, - binary.BigEndian.Uint32(ID.Suffix[:]), - } - rsvs, err := getSegReservations(ctx, x.db, "WHERE id_as = ? AND id_suffix = ?", params) - if err != nil { - return nil, err - } - switch len(rsvs) { - case 0: - return nil, nil - case 1: - return rsvs[0], nil - default: - return nil, db.NewDataError("more than 1 segment reservation found for an ID", nil, - "count", len(rsvs), "id.asid", ID.ASID, "id.suffix", hex.EncodeToString(ID.Suffix[:])) - } -} - -// GetSegmentRsvsFromSrcDstIA returns all reservations that start at src AS and end in dst AS. -func (x *executor) GetSegmentRsvsFromSrcDstIA(ctx context.Context, srcIA, dstIA addr.IA) ( - []*segment.Reservation, error) { - - conditions := make([]string, 0, 2) - params := make([]interface{}, 0, 2) - if !srcIA.IsZero() { - conditions = append(conditions, "src_ia = ?") - params = append(params, srcIA) - } - if !dstIA.IsZero() { - conditions = append(conditions, "dst_ia = ?") - params = append(params, dstIA) - } - if len(conditions) == 0 { - return nil, serrors.New("no src or dst ia provided") - } - condition := fmt.Sprintf("WHERE %s", strings.Join(conditions, " AND ")) - return getSegReservations(ctx, x.db, condition, params) -} - -// GetSegmentRsvFromPath searches for a segment reservation with the specified path. -func (x *executor) GetSegmentRsvFromPath(ctx context.Context, - path segment.ReservationTransparentPath) (*segment.Reservation, error) { - - rsvs, err := getSegReservations(ctx, x.db, "WHERE path = ?", []interface{}{path.ToRaw()}) - if err != nil { - return nil, err - } - switch len(rsvs) { - case 0: - return nil, nil - case 1: - return rsvs[0], nil - default: - return nil, db.NewDataError("more than 1 segment reservation found for a path", nil, - "path", path.String()) - } -} - -// GetAllSegmentRsvs returns all segment reservations. -func (x *executor) GetAllSegmentRsvs(ctx context.Context) ([]*segment.Reservation, error) { - return getSegReservations(ctx, x.db, "", nil) -} - -// GetSegmentRsvsFromIFPair returns all segment reservations that enter this AS at -// the specified ingress and exit at that egress. -func (x *executor) GetSegmentRsvsFromIFPair(ctx context.Context, ingress, egress *uint16) ( - []*segment.Reservation, error) { - - conditions := make([]string, 0, 2) - params := make([]interface{}, 0, 2) - if ingress != nil { - conditions = append(conditions, "ingress = ?") - params = append(params, *ingress) - } - if egress != nil { - conditions = append(conditions, "egress = ?") - params = append(params, *egress) - } - if len(conditions) == 0 { - return nil, serrors.New("no ingress or egress provided") - } - condition := fmt.Sprintf("WHERE %s", strings.Join(conditions, " AND ")) - return getSegReservations(ctx, x.db, condition, params) -} - -// NewSegmentRsv creates a new segment reservation in the DB, with an unused reservation ID. -// The reservation must contain at least one index. -// The created ID is set in the reservation pointer argument. -func (x *executor) NewSegmentRsv(ctx context.Context, rsv *segment.Reservation) error { - var err error - for retries := 0; retries < 3; retries++ { - err = db.DoInTx(ctx, x.db, func(ctx context.Context, tx *sql.Tx) error { - suffix, err := newSuffix(ctx, tx, rsv.ID.ASID) - if err != nil { - return err - } - if err := insertNewSegReservation(ctx, tx, rsv, suffix); err != nil { - return err - } - binary.BigEndian.PutUint32(rsv.ID.Suffix[:], suffix) - return nil - }) - if err == nil { - return nil - } - sqliteError, ok := err.(sqlite3.Error) - if !ok || sqliteError.Code != sqlite3.ErrConstraint { - return db.NewTxError("error inserting segment reservation", err) - } - } - return db.NewTxError("error inserting segment reservation after 3 retries", err) -} - -func (x *executor) PersistSegmentRsv(ctx context.Context, rsv *segment.Reservation) error { - err := db.DoInTx(ctx, x.db, func(ctx context.Context, tx *sql.Tx) error { - err := deleteSegmentRsv(ctx, tx, &rsv.ID) - if err != nil { - return err - } - suffix := binary.BigEndian.Uint32(rsv.ID.Suffix[:]) - return insertNewSegReservation(ctx, tx, rsv, suffix) - }) - if err != nil { - return db.NewTxError("error persisting reservation", err) - } - return nil -} - -// DeleteExpiredIndices will remove expired indices from the DB. If a reservation is left -// without any index after removing the expired ones, it will also be removed. This applies to -// both segment and e2e reservations. -func (x *executor) DeleteExpiredIndices(ctx context.Context, now time.Time) (int, error) { - deletedIndices := 0 - err := db.DoInTx(ctx, x.db, func(ctx context.Context, tx *sql.Tx) error { - // delete e2e indices - rowIDs, rsvRowIDs, err := getExpiredE2EIndexRowIDs(ctx, tx, now) - if err != nil { - return err - } - if len(rowIDs) > 0 { - // delete the segment indices pointed by rowIDs - n, err := deleteE2EIndicesFromRowIDs(ctx, tx, rowIDs) - if err != nil { - return err - } - deletedIndices = n - // delete empty reservations touched by previous removal - err = deleteEmptyE2EReservations(ctx, tx, rsvRowIDs) - if err != nil { - return err - } - } - - // delete segment indices - rowIDs, rsvRowIDs, err = getExpiredSegIndexRowIDs(ctx, tx, now) - if err != nil { - return err - } - if len(rowIDs) > 0 { - // delete the segment indices pointed by rowIDs - n, err := deleteSegIndicesFromRowIDs(ctx, tx, rowIDs) - if err != nil { - return err - } - deletedIndices += n - // delete empty reservations touched by previous removal - return deleteEmptySegReservations(ctx, tx, rsvRowIDs) - } - return nil - }) - return deletedIndices, err -} - -// DeleteSegmentRsv removes the segment reservation -func (x *executor) DeleteSegmentRsv(ctx context.Context, ID *reservation.SegmentID) error { - return deleteSegmentRsv(ctx, x.db, ID) -} - -// GetE2ERsvFromID finds the end to end resevation given its ID. -func (x *executor) GetE2ERsvFromID(ctx context.Context, ID *reservation.E2EID) ( - *e2e.Reservation, error) { - - var rsv *e2e.Reservation - err := db.DoInTx(ctx, x.db, func(ctx context.Context, tx *sql.Tx) error { - var err error - rsv, err = getE2ERsvFromID(ctx, tx, ID) - return err - }) - return rsv, err -} - -// GetE2ERsvsOnSegRsv returns the e2e reservations running on top of a given segment one. -func (x *executor) GetE2ERsvsOnSegRsv(ctx context.Context, ID *reservation.SegmentID) ( - []*e2e.Reservation, error) { - - var rsvs []*e2e.Reservation - err := db.DoInTx(ctx, x.db, func(ctx context.Context, tx *sql.Tx) error { - var err error - rsvs, err = getE2ERsvsFromSegment(ctx, tx, ID) - return err - }) - return rsvs, err -} - -func (x *executor) PersistE2ERsv(ctx context.Context, rsv *e2e.Reservation) error { - err := db.DoInTx(ctx, x.db, func(ctx context.Context, tx *sql.Tx) error { - err := deleteE2ERsv(ctx, tx, &rsv.ID) - if err != nil { - return err - } - return insertNewE2EReservation(ctx, tx, rsv) - }) - if err != nil { - return db.NewTxError("error persisting e2e reservation", err) - } - return nil -} - -// newSuffix finds a segment reservation ID suffix not being used at the moment. Should be called -// inside a transaction so the suffix is not used in the meantime, or fail. -func newSuffix(ctx context.Context, x db.Sqler, ASID addr.AS) (uint32, error) { - const query = `SELECT MIN(id_suffix)+1 FROM ( - SELECT 0 AS id_suffix UNION ALL - SELECT id_suffix FROM seg_reservation WHERE id_as = $1 - ) WHERE id_suffix+1 NOT IN (SELECT id_suffix FROM seg_reservation WHERE id_as = $1)` - var suffix uint32 - err := x.QueryRowContext(ctx, query, uint64(ASID)).Scan(&suffix) - switch { - case err == sql.ErrNoRows: - return 0, serrors.New("unexpected error getting new suffix: no rows") - case err != nil: - return 0, serrors.WrapStr("unexpected error getting new suffix", err) - } - return suffix, nil -} - -func insertNewSegReservation(ctx context.Context, x *sql.Tx, rsv *segment.Reservation, - suffix uint32) error { - - activeIndex := -1 - if rsv.ActiveIndex() != nil { - activeIndex = int(rsv.ActiveIndex().Idx) - } - const query = `INSERT INTO seg_reservation (id_as, id_suffix, ingress, egress, - path, end_props, traffic_split, src_ia, dst_ia,active_index) - VALUES (?, ?,?,?,?,?,?,?,?,?)` - res, err := x.ExecContext(ctx, query, rsv.ID.ASID, suffix, - rsv.Ingress, rsv.Egress, rsv.Path.ToRaw(), rsv.PathEndProps, rsv.TrafficSplit, - rsv.Path.GetSrcIA(), rsv.Path.GetDstIA(), activeIndex) - if err != nil { - return err - } - if len(rsv.Indices) > 0 { - rsvRowID, err := res.LastInsertId() - if err != nil { - return db.NewTxError("cannot obtain last insertion row id", err) - } - const queryIndexTmpl = `INSERT INTO seg_index (reservation, index_number, expiration, state, - min_bw, max_bw, alloc_bw, token) VALUES (?,?,?,?,?,?,?,?)` - params := make([]interface{}, 0, 8*len(rsv.Indices)) - for _, index := range rsv.Indices { - params = append(params, rsvRowID, index.Idx, - util.TimeToSecs(index.Expiration), index.State(), index.MinBW, index.MaxBW, - index.AllocBW, index.Token.ToRaw()) - } - q := queryIndexTmpl + strings.Repeat(",(?,?,?,?,?,?,?,?)", len(rsv.Indices)-1) - _, err = x.ExecContext(ctx, q, params...) - if err != nil { - return err - } - } - return nil -} - -type rsvFields struct { - RowID int - AsID uint64 - Suffix uint32 - Ingress uint16 - Egress uint16 - Path []byte - EndProps int - TrafficSplit int - ActiveIndex int -} - -func getSegReservations(ctx context.Context, x db.Sqler, condition string, params []interface{}) ( - []*segment.Reservation, error) { - - const queryTmpl = `SELECT ROWID,id_as,id_suffix,ingress,egress,path, - end_props,traffic_split,active_index - FROM seg_reservation %s` - query := fmt.Sprintf(queryTmpl, condition) - - rows, err := x.QueryContext(ctx, query, params...) - if err != nil { - return nil, err - } - defer rows.Close() - - reservationFields := []*rsvFields{} - for rows.Next() { - var f rsvFields - err := rows.Scan(&f.RowID, &f.AsID, &f.Suffix, &f.Ingress, &f.Egress, &f.Path, - &f.EndProps, &f.TrafficSplit, &f.ActiveIndex) - if err != nil { - return nil, err - } - reservationFields = append(reservationFields, &f) - } - if err := rows.Err(); err != nil { - return nil, err - } - - reservations := []*segment.Reservation{} - for _, rf := range reservationFields { - rsv, err := buildSegRsvFromFields(ctx, x, rf) - if err != nil { - return nil, err - } - reservations = append(reservations, rsv) - } - return reservations, nil -} - -// builds a segment.Reservation in memory from the fields and indices. -func buildSegRsvFromFields(ctx context.Context, x db.Sqler, fields *rsvFields) ( - *segment.Reservation, error) { - - indices, err := getSegIndices(ctx, x, fields.RowID) - if err != nil { - return nil, err - } - rsv := segment.NewReservation() - rsv.ID.ASID = addr.AS(fields.AsID) - binary.BigEndian.PutUint32(rsv.ID.Suffix[:], fields.Suffix) - rsv.Ingress = fields.Ingress - rsv.Egress = fields.Egress - p, err := segment.NewPathFromRaw(fields.Path) - if err != nil { - return nil, err - } - rsv.Path = p - rsv.PathEndProps = reservation.PathEndProps(fields.EndProps) - rsv.TrafficSplit = reservation.SplitCls(fields.TrafficSplit) - rsv.Indices = indices - if fields.ActiveIndex != -1 { - if err := rsv.SetIndexActive(reservation.IndexNumber(fields.ActiveIndex)); err != nil { - return nil, err - } - } - return rsv, nil -} - -// the rowID argument is the reservation row ID the indices belong to. -func getSegIndices(ctx context.Context, x db.Sqler, rowID int) (segment.Indices, error) { - const query = `SELECT index_number,expiration,state,min_bw,max_bw,alloc_bw,token - FROM seg_index WHERE reservation=?` - rows, err := x.QueryContext(ctx, query, rowID) - if err != nil { - return nil, db.NewReadError("cannot list indices", err) - } - defer rows.Close() - - indices := segment.Indices{} - var idx, expiration, state, minBW, maxBW, allocBW uint32 - var token []byte - for rows.Next() { - err := rows.Scan(&idx, &expiration, &state, &minBW, &maxBW, &allocBW, &token) - if err != nil { - return nil, db.NewReadError("could not get index values", err) - } - tok, err := reservation.TokenFromRaw(token) - if err != nil { - return nil, db.NewReadError("invalid stored token", err) - } - index := segment.NewIndex(reservation.IndexNumber(idx), - util.SecsToTime(expiration), segment.IndexState(state), reservation.BWCls(minBW), - reservation.BWCls(maxBW), reservation.BWCls(allocBW), tok) - indices = append(indices, *index) - } - if err := rows.Err(); err != nil { - return nil, err - } - // sort indices so they are consecutive modulo 16 - base.SortIndices(indices) - return indices, nil -} - -func deleteSegmentRsv(ctx context.Context, x db.Sqler, rsvID *reservation.SegmentID) error { - const query = `DELETE FROM seg_reservation WHERE id_as = ? AND id_suffix = ?` - suffix := binary.BigEndian.Uint32(rsvID.Suffix[:]) - _, err := x.ExecContext(ctx, query, rsvID.ASID, suffix) - return err -} - -func deleteE2ERsv(ctx context.Context, x db.Sqler, rsvID *reservation.E2EID) error { - const query = `DELETE FROM e2e_reservation WHERE reservation_id = ?` - _, err := x.ExecContext(ctx, query, rsvID.ToRaw()) - return err -} - -func insertNewE2EReservation(ctx context.Context, x *sql.Tx, rsv *e2e.Reservation) error { - const query = `INSERT INTO e2e_reservation (reservation_id) VALUES (?)` - res, err := x.ExecContext(ctx, query, rsv.ID.ToRaw()) - if err != nil { - return err - } - rowID, err := res.LastInsertId() - if err != nil { - return err - } - if len(rsv.Indices) > 0 { - const queryTmpl = `INSERT INTO e2e_index (reservation, index_number, expiration, - alloc_bw, token) VALUES (?,?,?,?,?)` - params := make([]interface{}, 0, 5*len(rsv.Indices)) - for _, index := range rsv.Indices { - params = append(params, rowID, index.Idx, util.TimeToSecs(index.Expiration), - index.AllocBW, index.Token.ToRaw()) - } - query := queryTmpl + strings.Repeat(",(?,?,?,?,?)", len(rsv.Indices)-1) - _, err := x.ExecContext(ctx, query, params...) - if err != nil { - return err - } - } - if len(rsv.SegmentReservations) > 0 { - const valuesPlaceholder = `(id_as = ? AND id_suffix = ?)` - const queryTmpl = `INSERT INTO e2e_to_seg (e2e, seg) - SELECT ?, ROWID FROM seg_reservation WHERE ` - params := make([]interface{}, 1, 1+2*len(rsv.SegmentReservations)) - params[0] = rowID - for _, segRsv := range rsv.SegmentReservations { - params = append(params, segRsv.ID.ASID, binary.BigEndian.Uint32(segRsv.ID.Suffix[:])) - } - query := queryTmpl + valuesPlaceholder + - strings.Repeat(" OR "+valuesPlaceholder, len(rsv.SegmentReservations)-1) - res, err := x.ExecContext(ctx, query, params...) - if err != nil { - return err - } - n, err := res.RowsAffected() - if err != nil { - return err - } - if int(n) != len(rsv.SegmentReservations) { - return serrors.New("not all referenced segment reservations are in DB", - "expected", len(rsv.SegmentReservations), "actual", n) - } - } - return nil -} - -func getE2ERsvFromID(ctx context.Context, x *sql.Tx, ID *reservation.E2EID) ( - *e2e.Reservation, error) { - - // read reservation - var rowID int - const query = `SELECT ROWID FROM e2e_reservation WHERE reservation_id = ?` - err := x.QueryRowContext(ctx, query, ID.ToRaw()).Scan(&rowID) - if err != nil { - if err == sql.ErrNoRows { - return nil, nil - } - return nil, err - } - // read indices - indices, err := getE2EIndices(ctx, x, rowID) - if err != nil { - return nil, err - } - // sort indices so they are consecutive modulo 16 - base.SortIndices(indices) - // read assoc segment reservations - segRsvs, err := getE2EAssocSegRsvs(ctx, x, rowID) - if err != nil { - return nil, err - } - rsv := &e2e.Reservation{ - ID: *ID, - Indices: indices, - SegmentReservations: segRsvs, - } - return rsv, nil -} - -func getE2ERsvsFromSegment(ctx context.Context, x *sql.Tx, ID *reservation.SegmentID) ( - []*e2e.Reservation, error) { - - rowID2e2eIDs := make(map[int]*reservation.E2EID) - const query = `SELECT ROWID,reservation_id FROM e2e_reservation WHERE ROWID IN ( - SELECT e2e FROM e2e_to_seg WHERE seg = ( - SELECT ROWID FROM seg_reservation WHERE id_as = ? AND id_suffix = ? - ))` - suffix := binary.BigEndian.Uint32(ID.Suffix[:]) - rows, err := x.QueryContext(ctx, query, ID.ASID, suffix) - if err != nil { - return nil, err - } - defer rows.Close() - for rows.Next() { - var rowID int - var rsvID []byte - err := rows.Scan(&rowID, &rsvID) - if err != nil { - return nil, err - } - id, err := reservation.E2EIDFromRaw(rsvID) - if err != nil { - return nil, err - } - rowID2e2eIDs[rowID] = id - } - if err := rows.Err(); err != nil { - return nil, err - } - rsvs := make([]*e2e.Reservation, 0, len(rowID2e2eIDs)) - for rowID, e2eID := range rowID2e2eIDs { - // read indices - indices, err := getE2EIndices(ctx, x, rowID) - if err != nil { - return nil, err - } - // read assoc segment reservations - segRsvs, err := getE2EAssocSegRsvs(ctx, x, rowID) - if err != nil { - return nil, err - } - rsv := &e2e.Reservation{ - ID: *e2eID, - Indices: indices, - SegmentReservations: segRsvs, - } - rsvs = append(rsvs, rsv) - } - return rsvs, nil -} - -func getE2EIndices(ctx context.Context, x db.Sqler, rowID int) (e2e.Indices, error) { - const query = `SELECT index_number, expiration, alloc_bw, token FROM e2e_index - WHERE reservation = ?` - rows, err := x.QueryContext(ctx, query, rowID) - if err != nil { - return nil, err - } - defer rows.Close() - indices := e2e.Indices{} - for rows.Next() { - var idx, expiration, allocBW uint32 - var token []byte - err := rows.Scan(&idx, &expiration, &allocBW, &token) - if err != nil { - return nil, err - } - tok, err := reservation.TokenFromRaw(token) - if err != nil { - return nil, err - } - indices = append(indices, e2e.Index{ - Idx: reservation.IndexNumber(idx), - Expiration: util.SecsToTime(expiration), - AllocBW: reservation.BWCls(allocBW), - Token: tok, - }) - } - if err := rows.Err(); err != nil { - return nil, err - } - return indices, nil -} - -// rowID is the row ID of the E2E reservation -func getE2EAssocSegRsvs(ctx context.Context, x db.Sqler, rowID int) ( - []*segment.Reservation, error) { - - condition := "WHERE rowID IN (SELECT seg FROM e2e_to_seg WHERE e2e = ?)" - return getSegReservations(ctx, x, condition, []interface{}{rowID}) -} - -// returns the rowIDs of the indices and their associated segment reservation rowID -func getExpiredSegIndexRowIDs(ctx context.Context, x db.Sqler, now time.Time) ( - []interface{}, []interface{}, error) { - - const query = `SELECT rowID, reservation FROM seg_index WHERE expiration < ?` - expTime := util.TimeToSecs(now) - rows, err := x.QueryContext(ctx, query, expTime) - if err != nil { - return nil, nil, err - } - defer rows.Close() - rowIDs := make([]interface{}, 0) - rsvRowIDs := make([]interface{}, 0) - for rows.Next() { - var indexID, rsvRowID int - err := rows.Scan(&indexID, &rsvRowID) - if err != nil { - return nil, nil, err - } - rowIDs = append(rowIDs, indexID) - rsvRowIDs = append(rsvRowIDs, rsvRowID) - } - if err := rows.Err(); err != nil { - return nil, nil, err - } - return rowIDs, rsvRowIDs, nil -} - -func deleteSegIndicesFromRowIDs(ctx context.Context, x db.Sqler, rowIDs []interface{}) ( - int, error) { - - const queryTmpl = `DELETE FROM seg_index WHERE ROWID IN (?%s)` - query := fmt.Sprintf(queryTmpl, strings.Repeat(",?", len(rowIDs)-1)) - res, err := x.ExecContext(ctx, query, rowIDs...) - if err != nil { - return 0, err - } - n, err := res.RowsAffected() - if err != nil { - return 0, err - } - return int(n), nil -} - -// deletes segment reservations from the rowIDs if they have no indices -func deleteEmptySegReservations(ctx context.Context, x db.Sqler, rowIDs []interface{}) error { - const queryTmpl = `DELETE FROM seg_reservation AS r WHERE NOT EXISTS ( - SELECT NULL FROM seg_index AS idx WHERE idx.reservation=r.ROWID - ) AND r.ROWID IN (?%s);` - query := fmt.Sprintf(queryTmpl, strings.Repeat(",?", len(rowIDs)-1)) - _, err := x.ExecContext(ctx, query, rowIDs...) - return err -} - -func getExpiredE2EIndexRowIDs(ctx context.Context, x db.Sqler, now time.Time) ( - []interface{}, []interface{}, error) { - - const query = `SELECT ROWID, reservation FROM e2e_index WHERE expiration < ?` - expTime := util.TimeToSecs(now) - rows, err := x.QueryContext(ctx, query, expTime) - if err != nil { - return nil, nil, err - } - defer rows.Close() - rowIDs := make([]interface{}, 0) - rsvRowIDs := make([]interface{}, 0) - for rows.Next() { - var indexID, rsvRowID int - err := rows.Scan(&indexID, &rsvRowID) - if err != nil { - return nil, nil, err - } - rowIDs = append(rowIDs, indexID) - rsvRowIDs = append(rsvRowIDs, rsvRowID) - } - if err := rows.Err(); err != nil { - return nil, nil, err - } - return rowIDs, rsvRowIDs, nil -} - -func deleteE2EIndicesFromRowIDs(ctx context.Context, x db.Sqler, rowIDs []interface{}) ( - int, error) { - - const queryTmpl = `DELETE FROM e2e_index WHERE ROWID IN (?%s)` - query := fmt.Sprintf(queryTmpl, strings.Repeat(",?", len(rowIDs)-1)) - res, err := x.ExecContext(ctx, query, rowIDs...) - if err != nil { - return 0, err - } - n, err := res.RowsAffected() - if err != nil { - return 0, err - } - return int(n), nil -} - -// deletes e2e reservations from the rowIDs if they have no indices -func deleteEmptyE2EReservations(ctx context.Context, x db.Sqler, rowIDs []interface{}) error { - const queryTmpl = `DELETE FROM e2e_reservation AS r WHERE NOT EXISTS ( - SELECT NULL FROM e2e_index AS idx WHERE idx.reservation=r.ROWID - ) AND r.ROWID IN (?%s);` - query := fmt.Sprintf(queryTmpl, strings.Repeat(",?", len(rowIDs)-1)) - _, err := x.ExecContext(ctx, query, rowIDs...) - return err -} diff --git a/control/colibri/reservation/sqlite/db_test.go b/control/colibri/reservation/sqlite/db_test.go deleted file mode 100644 index b9c4edead..000000000 --- a/control/colibri/reservation/sqlite/db_test.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2020 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 sqlite - -import ( - "context" - "database/sql" - "testing" - - "github.com/mattn/go-sqlite3" - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/control/colibri/reservation/reservationdbtest" - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/xtest" -) - -type TestDB struct { - *Backend -} - -func (b *TestDB) Prepare(t *testing.T, _ context.Context) { - b.Backend = newDB(t) -} - -func TestReservationDBSuite(t *testing.T) { - db := &TestDB{} - reservationdbtest.TestDB(t, db) -} - -func TestNewSuffix(t *testing.T) { - ctx := context.Background() - asid := xtest.MustParseAS("ff00:0:1") - db := newDB(t) - suffix, err := newSuffix(ctx, db.db, asid) - require.NoError(t, err) - require.Equal(t, uint32(1), suffix) - // add reservations - addSegRsvRows(t, db, asid, 3, 5) - suffix, err = newSuffix(ctx, db.db, asid) - require.NoError(t, err) - require.Equal(t, uint32(1), suffix) - addSegRsvRows(t, db, asid, 1, 2) - suffix, err = newSuffix(ctx, db.db, asid) - require.NoError(t, err) - require.Equal(t, uint32(6), suffix) -} - -func TestRaceForSuffix(t *testing.T) { - ctx := context.Background() - asid := xtest.MustParseAS("ff00:0:1") - db := newDB(t) - addSegRsvRows(t, db, asid, 1, 2) - suffix1, err := newSuffix(ctx, db.db, asid) - require.NoError(t, err) - require.Equal(t, uint32(3), suffix1) - suffix2, err := newSuffix(ctx, db.db, asid) - require.NoError(t, err) - require.Equal(t, uint32(3), suffix2) - rsv := &segment.Reservation{ - ID: reservation.SegmentID{ASID: asid}, - Indices: segment.Indices{segment.Index{}}, - } - err = testInsertNewSegReservation(ctx, t, db.db, rsv, suffix1) - require.NoError(t, err) - err = testInsertNewSegReservation(ctx, t, db.db, rsv, suffix2) - require.Error(t, err) - sqliteError, ok := err.(sqlite3.Error) - require.True(t, ok) - require.Equal(t, sqlite3.ErrConstraint, sqliteError.Code) -} - -func BenchmarkNewSuffix10K(b *testing.B) { benchmarkNewSuffix(b, 10000) } -func BenchmarkNewSuffix100K(b *testing.B) { benchmarkNewSuffix(b, 100000) } -func BenchmarkNewSuffix1M(b *testing.B) { benchmarkNewSuffix(b, 1000000) } - -func newDB(t testing.TB) *Backend { - t.Helper() - db, err := New("file::memory:") - require.NoError(t, err) - return db -} - -func addSegRsvRows(t testing.TB, b *Backend, asid addr.AS, firstSuffix, lastSuffix uint32) { - t.Helper() - ctx := context.Background() - query := `INSERT INTO seg_reservation (id_as, id_suffix, ingress, egress, path, - end_props, traffic_split, src_ia, dst_ia, active_index) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, -1)` - for suffix := firstSuffix; suffix <= lastSuffix; suffix++ { - _, err := b.db.ExecContext(ctx, query, asid, suffix, 0, 0, nil, 0, 0, nil, nil) - require.NoError(t, err) - } -} - -func testInsertNewSegReservation(ctx context.Context, t *testing.T, db *sql.DB, - rsv *segment.Reservation, suffix uint32) error { - - tx, err := db.BeginTx(ctx, nil) - require.NoError(t, err) - defer tx.Rollback() - err = insertNewSegReservation(ctx, tx, rsv, suffix) - if err != nil { - return err - } - return tx.Commit() -} - -func benchmarkNewSuffix(b *testing.B, entries uint32) { - db := newDB(b) - ctx := context.Background() - asid := xtest.MustParseAS("ff00:0:1") - addSegRsvRows(b, db, asid, 1, entries) - b.ResetTimer() - - for n := 0; n < b.N; n++ { - suffix, err := newSuffix(ctx, db.db, asid) - require.NoError(b, err) - require.Equal(b, entries+1, suffix) - } -} diff --git a/control/colibri/reservation/sqlite/schema.go b/control/colibri/reservation/sqlite/schema.go deleted file mode 100644 index 6762c69ff..000000000 --- a/control/colibri/reservation/sqlite/schema.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2020 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 sqlite - -const ( - // SchemaVersion is the version of the SQLite schema understood by this backend. - // Whenever changes to the schema are made, this version number should be increased - // to prevent data corruption between incompatible database schemas. - SchemaVersion = 1 - // Schema is the SQLite database layout. - Schema = `CREATE TABLE seg_reservation ( - ROWID INTEGER, - id_as INTEGER NOT NULL, - id_suffix INTEGER NOT NULL, - ingress INTEGER NOT NULL, - egress INTEGER NOT NULL, - path BLOB, - end_props INTEGER NOT NULL, - traffic_split INTEGER NOT NULL, - src_ia INTEGER, - dst_ia INTEGER, - active_index INTEGER NOT NULL, - PRIMARY KEY(ROWID), - UNIQUE(id_as,id_suffix), - UNIQUE(path) - ); - CREATE TABLE seg_index ( - reservation INTEGER NOT NULL, - index_number INTEGER NOT NULL, - expiration INTEGER NOT NULL, - state INTEGER NOT NULL, - min_bw INTEGER NOT NULL, - max_bw INTEGER NOT NULL, - alloc_bw INTEGER NOT NULL, - token BLOB, - PRIMARY KEY(reservation,index_number), - FOREIGN KEY(reservation) REFERENCES seg_reservation(ROWID) ON DELETE CASCADE - ); - CREATE TABLE e2e_reservation ( - ROWID INTEGER, - reservation_id BLOB NOT NULL, - UNIQUE(reservation_id), - PRIMARY KEY(ROWID) - ); - CREATE TABLE e2e_index ( - reservation INTEGER NOT NULL, - index_number INTEGER NOT NULL, - expiration INTEGER NOT NULL, - alloc_bw INTEGER NOT NULL, - token BLOB, - PRIMARY KEY(reservation,index_number), - FOREIGN KEY(reservation) REFERENCES e2e_reservation(ROWID) ON DELETE CASCADE - ); - CREATE TABLE e2e_to_seg ( - e2e INTEGER NOT NULL, - seg INTEGER NOT NULL, - PRIMARY KEY(e2e,seg), - FOREIGN KEY(seg) REFERENCES seg_reservation(ROWID) ON DELETE CASCADE, - FOREIGN KEY(e2e) REFERENCES e2e_reservation(ROWID) ON DELETE CASCADE - ); - CREATE INDEX "index_seg_reservation" ON "seg_reservation" ( - "id_as", - "id_suffix" - ); - CREATE INDEX "index2_seg_reservation" ON "seg_reservation" ( - "ingress" - ); - CREATE INDEX "index3_seg_reservation" ON "seg_reservation" ( - "egress" - ); - CREATE UNIQUE INDEX "index4_seg_reservation" ON "seg_reservation" ( - "path" - ); - CREATE UNIQUE INDEX "index_seg_index" ON "seg_index" ( - "reservation", - "index_number" - ); - CREATE UNIQUE INDEX "index_e2e_reservation" ON "e2e_reservation" ( - "reservation_id" - ); - CREATE UNIQUE INDEX "index_e2e_index" ON "e2e_index" ( - "reservation", - "index_number" - ); - CREATE INDEX "index_e2e_to_seg" ON "e2e_to_seg" ( - "e2e" - ); - CREATE INDEX "index2_e2e_to_seg" ON "e2e_to_seg" ( - "seg" - );` -) diff --git a/control/colibri/reservation/test/BUILD.bazel b/control/colibri/reservation/test/BUILD.bazel deleted file mode 100644 index 74bb10dd4..000000000 --- a/control/colibri/reservation/test/BUILD.bazel +++ /dev/null @@ -1,9 +0,0 @@ -load("//tools/lint:go.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["path.go"], - importpath = "github.com/scionproto/scion/control/colibri/reservation/test", - visibility = ["//visibility:public"], - deps = ["//control/colibri/reservation:go_default_library"], -) diff --git a/control/colibri/reservation/test/path.go b/control/colibri/reservation/test/path.go deleted file mode 100644 index ecf81a2db..000000000 --- a/control/colibri/reservation/test/path.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 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 test - -import ( - base "github.com/scionproto/scion/control/colibri/reservation" -) - -type TestColibriPath struct { - HopCount int - CurrentHop int - Ingress uint16 - Egress uint16 -} - -var _ base.ColibriPath = (*TestColibriPath)(nil) - -func (p *TestColibriPath) Copy() base.ColibriPath { - return p -} - -func (p *TestColibriPath) Reverse() error { - return nil -} - -func (p *TestColibriPath) NumberOfHops() int { - return p.HopCount -} - -func (p *TestColibriPath) IndexOfCurrentHop() int { - return p.CurrentHop -} - -func (p *TestColibriPath) IngressEgressIFIDs() (uint16, uint16) { - return p.Ingress, p.Egress -} - -// NewTestPath returns a new path with one segment consisting on 3 hopfields: (0,2)->(1,2)->(1,0). -func NewTestPath() base.ColibriPath { - path := TestColibriPath{ - Ingress: 1, - Egress: 2, - } - return &path -} diff --git a/control/colibri/reservation/types.go b/control/colibri/reservation/types.go deleted file mode 100644 index 300ed5765..000000000 --- a/control/colibri/reservation/types.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 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 reservation - -// Capacities describes what a capacity description must offer. -type Capacities interface { - IngressInterfaces() []uint16 - EgressInterfaces() []uint16 - Capacity(from, to uint16) uint64 - CapacityIngress(ingress uint16) uint64 - CapacityEgress(egress uint16) uint64 -} - -// ColibriPath is a path of type COLIBRI. -// This type will be moved to its right place in slayers once the header has been approved. -// TODO(juagargi): move the type to slayers. -type ColibriPath interface { - Copy() ColibriPath - // Reverse reverses the contained path. - Reverse() error - NumberOfHops() int - IndexOfCurrentHop() int - IngressEgressIFIDs() (uint16, uint16) -} - -// MessageWithPath is used to send messages from the COLIBRI service via the BR. -type MessageWithPath interface { - Path() ColibriPath - // Payload() []byte -} diff --git a/control/colibri/reservationstorage/BUILD.bazel b/control/colibri/reservationstorage/BUILD.bazel deleted file mode 100644 index 1f749c5dc..000000000 --- a/control/colibri/reservationstorage/BUILD.bazel +++ /dev/null @@ -1,14 +0,0 @@ -load("//tools/lint:go.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["store.go"], - importpath = "github.com/scionproto/scion/control/colibri/reservationstorage", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation:go_default_library", - "//control/colibri/reservation/e2e:go_default_library", - "//control/colibri/reservation/segment:go_default_library", - "//private/storage/cleaner:go_default_library", - ], -) diff --git a/control/colibri/reservationstorage/backend/BUILD.bazel b/control/colibri/reservationstorage/backend/BUILD.bazel deleted file mode 100644 index c328c5ad9..000000000 --- a/control/colibri/reservationstorage/backend/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -load("//tools/lint:go.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["db.go"], - importpath = "github.com/scionproto/scion/control/colibri/reservationstorage/backend", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation/e2e:go_default_library", - "//control/colibri/reservation/segment:go_default_library", - "//pkg/addr:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//private/storage/db:go_default_library", - ], -) diff --git a/control/colibri/reservationstorage/backend/db.go b/control/colibri/reservationstorage/backend/db.go deleted file mode 100644 index a99a1da22..000000000 --- a/control/colibri/reservationstorage/backend/db.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2020 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 backend - -import ( - "context" - "database/sql" - "io" - "time" - - "github.com/scionproto/scion/control/colibri/reservation/e2e" - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/private/storage/db" -) - -// ReserverOnly has the methods available to the AS that starts the reservation. -type ReserverOnly interface { - // GetSegmentRsvsFromSrcDstIA returns all reservations that start at src AS and end in dst AS. - GetSegmentRsvsFromSrcDstIA(ctx context.Context, srcIA, dstIA addr.IA) ( - []*segment.Reservation, error) - // GetSegmentRsvFromPath searches for a segment reservation with the specified path. - GetSegmentRsvFromPath(ctx context.Context, path segment.ReservationTransparentPath) ( - *segment.Reservation, error) - - // NewSegmentRsv creates a new segment reservation in the DB, with an unused reservation ID. - // The created ID is set in the reservation pointer argument. Used by setup req. - NewSegmentRsv(ctx context.Context, rsv *segment.Reservation) error -} - -// TransitOnly represents an AS in-path of a reservation, not the one originating it. -type TransitOnly interface { - // GetAllSegmentRsvs returns all segment reservations. Used by setup req. - GetAllSegmentRsvs(ctx context.Context) ([]*segment.Reservation, error) - // GetSegmentRsvsFromIFPair returns all segment reservations that enter this AS at - // the specified ingress and exit at that egress. Used by setup req. - GetSegmentRsvsFromIFPair(ctx context.Context, ingress, egress *uint16) ( - []*segment.Reservation, error) -} - -// ReserverAndTransit contains the functionality for any AS that has a COLIBRI service. -type ReserverAndTransit interface { - // GetSegmentRsvFromID will return the reservation with that ID. - // Used by setup/renew req/resp. and any request. - GetSegmentRsvFromID(ctx context.Context, ID *reservation.SegmentID) ( - *segment.Reservation, error) - // PersistSegmentRsv ensures the DB contains the reservation as represented in rsv. - PersistSegmentRsv(ctx context.Context, rsv *segment.Reservation) error - // DeleteSegmentRsv removes the segment reservation. Used in teardown. - DeleteSegmentRsv(ctx context.Context, ID *reservation.SegmentID) error - - // DeleteExpiredIndices will remove expired indices from the DB. If a reservation is left - // without any index after removing the expired ones, it will also be removed. This applies to - // both segment and e2e reservations. - // Used on schedule. - DeleteExpiredIndices(ctx context.Context, now time.Time) (int, error) - - // GetE2ERsvFromID finds the end to end resevation given its ID. - GetE2ERsvFromID(ctx context.Context, ID *reservation.E2EID) (*e2e.Reservation, error) - // GetE2ERsvsOnSegRsv returns the e2e reservations running on top of a given segment one. - GetE2ERsvsOnSegRsv(ctx context.Context, ID *reservation.SegmentID) ([]*e2e.Reservation, error) - // PersistE2ERsv makes the DB reflect the same contents as the rsv parameter. - PersistE2ERsv(ctx context.Context, rsv *e2e.Reservation) error -} - -type Transaction interface { - ReserverOnly - TransitOnly - ReserverAndTransit - Commit() error - Rollback() error -} - -// DB is the interface for any reservation backend. -type DB interface { - BeginTransaction(ctx context.Context, opts *sql.TxOptions) (Transaction, error) - ReserverOnly - TransitOnly - ReserverAndTransit - db.LimitSetter - io.Closer -} diff --git a/control/colibri/reservationstorage/backend/mock_backend/BUILD.bazel b/control/colibri/reservationstorage/backend/mock_backend/BUILD.bazel deleted file mode 100644 index f6c9ed1ad..000000000 --- a/control/colibri/reservationstorage/backend/mock_backend/BUILD.bazel +++ /dev/null @@ -1,28 +0,0 @@ -load("//tools/lint:go.bzl", "go_library") -load("@io_bazel_rules_go//go:def.bzl", "gomock") - -gomock( - name = "go_default_mock", - out = "mock.go", - interfaces = [ - "DB", - "Transaction", - ], - library = "//control/colibri/reservationstorage/backend:go_default_library", - package = "mock_backend", -) - -go_library( - name = "go_default_library", - srcs = ["mock.go"], - importpath = "github.com/scionproto/scion/control/colibri/reservationstorage/backend/mock_backend", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation/e2e:go_default_library", - "//control/colibri/reservation/segment:go_default_library", - "//control/colibri/reservationstorage/backend:go_default_library", - "//pkg/addr:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "@com_github_golang_mock//gomock:go_default_library", - ], -) diff --git a/control/colibri/reservationstorage/backend/mock_backend/mock.go b/control/colibri/reservationstorage/backend/mock_backend/mock.go deleted file mode 100644 index fb8eb1629..000000000 --- a/control/colibri/reservationstorage/backend/mock_backend/mock.go +++ /dev/null @@ -1,498 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/scionproto/scion/control/colibri/reservationstorage/backend (interfaces: DB,Transaction) - -// Package mock_backend is a generated GoMock package. -package mock_backend - -import ( - context "context" - sql "database/sql" - reflect "reflect" - time "time" - - gomock "github.com/golang/mock/gomock" - e2e "github.com/scionproto/scion/control/colibri/reservation/e2e" - segment "github.com/scionproto/scion/control/colibri/reservation/segment" - backend "github.com/scionproto/scion/control/colibri/reservationstorage/backend" - addr "github.com/scionproto/scion/pkg/addr" - reservation "github.com/scionproto/scion/pkg/experimental/colibri/reservation" -) - -// MockDB is a mock of DB interface. -type MockDB struct { - ctrl *gomock.Controller - recorder *MockDBMockRecorder -} - -// MockDBMockRecorder is the mock recorder for MockDB. -type MockDBMockRecorder struct { - mock *MockDB -} - -// NewMockDB creates a new mock instance. -func NewMockDB(ctrl *gomock.Controller) *MockDB { - mock := &MockDB{ctrl: ctrl} - mock.recorder = &MockDBMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockDB) EXPECT() *MockDBMockRecorder { - return m.recorder -} - -// BeginTransaction mocks base method. -func (m *MockDB) BeginTransaction(arg0 context.Context, arg1 *sql.TxOptions) (backend.Transaction, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BeginTransaction", arg0, arg1) - ret0, _ := ret[0].(backend.Transaction) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// BeginTransaction indicates an expected call of BeginTransaction. -func (mr *MockDBMockRecorder) BeginTransaction(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeginTransaction", reflect.TypeOf((*MockDB)(nil).BeginTransaction), arg0, arg1) -} - -// Close mocks base method. -func (m *MockDB) Close() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Close") - ret0, _ := ret[0].(error) - return ret0 -} - -// Close indicates an expected call of Close. -func (mr *MockDBMockRecorder) Close() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockDB)(nil).Close)) -} - -// DeleteExpiredIndices mocks base method. -func (m *MockDB) DeleteExpiredIndices(arg0 context.Context, arg1 time.Time) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteExpiredIndices", arg0, arg1) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DeleteExpiredIndices indicates an expected call of DeleteExpiredIndices. -func (mr *MockDBMockRecorder) DeleteExpiredIndices(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteExpiredIndices", reflect.TypeOf((*MockDB)(nil).DeleteExpiredIndices), arg0, arg1) -} - -// DeleteSegmentRsv mocks base method. -func (m *MockDB) DeleteSegmentRsv(arg0 context.Context, arg1 *reservation.SegmentID) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteSegmentRsv", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteSegmentRsv indicates an expected call of DeleteSegmentRsv. -func (mr *MockDBMockRecorder) DeleteSegmentRsv(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSegmentRsv", reflect.TypeOf((*MockDB)(nil).DeleteSegmentRsv), arg0, arg1) -} - -// GetAllSegmentRsvs mocks base method. -func (m *MockDB) GetAllSegmentRsvs(arg0 context.Context) ([]*segment.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAllSegmentRsvs", arg0) - ret0, _ := ret[0].([]*segment.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetAllSegmentRsvs indicates an expected call of GetAllSegmentRsvs. -func (mr *MockDBMockRecorder) GetAllSegmentRsvs(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllSegmentRsvs", reflect.TypeOf((*MockDB)(nil).GetAllSegmentRsvs), arg0) -} - -// GetE2ERsvFromID mocks base method. -func (m *MockDB) GetE2ERsvFromID(arg0 context.Context, arg1 *reservation.E2EID) (*e2e.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetE2ERsvFromID", arg0, arg1) - ret0, _ := ret[0].(*e2e.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetE2ERsvFromID indicates an expected call of GetE2ERsvFromID. -func (mr *MockDBMockRecorder) GetE2ERsvFromID(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetE2ERsvFromID", reflect.TypeOf((*MockDB)(nil).GetE2ERsvFromID), arg0, arg1) -} - -// GetE2ERsvsOnSegRsv mocks base method. -func (m *MockDB) GetE2ERsvsOnSegRsv(arg0 context.Context, arg1 *reservation.SegmentID) ([]*e2e.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetE2ERsvsOnSegRsv", arg0, arg1) - ret0, _ := ret[0].([]*e2e.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetE2ERsvsOnSegRsv indicates an expected call of GetE2ERsvsOnSegRsv. -func (mr *MockDBMockRecorder) GetE2ERsvsOnSegRsv(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetE2ERsvsOnSegRsv", reflect.TypeOf((*MockDB)(nil).GetE2ERsvsOnSegRsv), arg0, arg1) -} - -// GetSegmentRsvFromID mocks base method. -func (m *MockDB) GetSegmentRsvFromID(arg0 context.Context, arg1 *reservation.SegmentID) (*segment.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSegmentRsvFromID", arg0, arg1) - ret0, _ := ret[0].(*segment.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSegmentRsvFromID indicates an expected call of GetSegmentRsvFromID. -func (mr *MockDBMockRecorder) GetSegmentRsvFromID(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSegmentRsvFromID", reflect.TypeOf((*MockDB)(nil).GetSegmentRsvFromID), arg0, arg1) -} - -// GetSegmentRsvFromPath mocks base method. -func (m *MockDB) GetSegmentRsvFromPath(arg0 context.Context, arg1 segment.ReservationTransparentPath) (*segment.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSegmentRsvFromPath", arg0, arg1) - ret0, _ := ret[0].(*segment.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSegmentRsvFromPath indicates an expected call of GetSegmentRsvFromPath. -func (mr *MockDBMockRecorder) GetSegmentRsvFromPath(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSegmentRsvFromPath", reflect.TypeOf((*MockDB)(nil).GetSegmentRsvFromPath), arg0, arg1) -} - -// GetSegmentRsvsFromIFPair mocks base method. -func (m *MockDB) GetSegmentRsvsFromIFPair(arg0 context.Context, arg1, arg2 *uint16) ([]*segment.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSegmentRsvsFromIFPair", arg0, arg1, arg2) - ret0, _ := ret[0].([]*segment.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSegmentRsvsFromIFPair indicates an expected call of GetSegmentRsvsFromIFPair. -func (mr *MockDBMockRecorder) GetSegmentRsvsFromIFPair(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSegmentRsvsFromIFPair", reflect.TypeOf((*MockDB)(nil).GetSegmentRsvsFromIFPair), arg0, arg1, arg2) -} - -// GetSegmentRsvsFromSrcDstIA mocks base method. -func (m *MockDB) GetSegmentRsvsFromSrcDstIA(arg0 context.Context, arg1, arg2 addr.IA) ([]*segment.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSegmentRsvsFromSrcDstIA", arg0, arg1, arg2) - ret0, _ := ret[0].([]*segment.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSegmentRsvsFromSrcDstIA indicates an expected call of GetSegmentRsvsFromSrcDstIA. -func (mr *MockDBMockRecorder) GetSegmentRsvsFromSrcDstIA(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSegmentRsvsFromSrcDstIA", reflect.TypeOf((*MockDB)(nil).GetSegmentRsvsFromSrcDstIA), arg0, arg1, arg2) -} - -// NewSegmentRsv mocks base method. -func (m *MockDB) NewSegmentRsv(arg0 context.Context, arg1 *segment.Reservation) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewSegmentRsv", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// NewSegmentRsv indicates an expected call of NewSegmentRsv. -func (mr *MockDBMockRecorder) NewSegmentRsv(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewSegmentRsv", reflect.TypeOf((*MockDB)(nil).NewSegmentRsv), arg0, arg1) -} - -// PersistE2ERsv mocks base method. -func (m *MockDB) PersistE2ERsv(arg0 context.Context, arg1 *e2e.Reservation) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PersistE2ERsv", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// PersistE2ERsv indicates an expected call of PersistE2ERsv. -func (mr *MockDBMockRecorder) PersistE2ERsv(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PersistE2ERsv", reflect.TypeOf((*MockDB)(nil).PersistE2ERsv), arg0, arg1) -} - -// PersistSegmentRsv mocks base method. -func (m *MockDB) PersistSegmentRsv(arg0 context.Context, arg1 *segment.Reservation) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PersistSegmentRsv", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// PersistSegmentRsv indicates an expected call of PersistSegmentRsv. -func (mr *MockDBMockRecorder) PersistSegmentRsv(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PersistSegmentRsv", reflect.TypeOf((*MockDB)(nil).PersistSegmentRsv), arg0, arg1) -} - -// SetMaxIdleConns mocks base method. -func (m *MockDB) SetMaxIdleConns(arg0 int) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetMaxIdleConns", arg0) -} - -// SetMaxIdleConns indicates an expected call of SetMaxIdleConns. -func (mr *MockDBMockRecorder) SetMaxIdleConns(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMaxIdleConns", reflect.TypeOf((*MockDB)(nil).SetMaxIdleConns), arg0) -} - -// SetMaxOpenConns mocks base method. -func (m *MockDB) SetMaxOpenConns(arg0 int) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetMaxOpenConns", arg0) -} - -// SetMaxOpenConns indicates an expected call of SetMaxOpenConns. -func (mr *MockDBMockRecorder) SetMaxOpenConns(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMaxOpenConns", reflect.TypeOf((*MockDB)(nil).SetMaxOpenConns), arg0) -} - -// MockTransaction is a mock of Transaction interface. -type MockTransaction struct { - ctrl *gomock.Controller - recorder *MockTransactionMockRecorder -} - -// MockTransactionMockRecorder is the mock recorder for MockTransaction. -type MockTransactionMockRecorder struct { - mock *MockTransaction -} - -// NewMockTransaction creates a new mock instance. -func NewMockTransaction(ctrl *gomock.Controller) *MockTransaction { - mock := &MockTransaction{ctrl: ctrl} - mock.recorder = &MockTransactionMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockTransaction) EXPECT() *MockTransactionMockRecorder { - return m.recorder -} - -// Commit mocks base method. -func (m *MockTransaction) Commit() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Commit") - ret0, _ := ret[0].(error) - return ret0 -} - -// Commit indicates an expected call of Commit. -func (mr *MockTransactionMockRecorder) Commit() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Commit", reflect.TypeOf((*MockTransaction)(nil).Commit)) -} - -// DeleteExpiredIndices mocks base method. -func (m *MockTransaction) DeleteExpiredIndices(arg0 context.Context, arg1 time.Time) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteExpiredIndices", arg0, arg1) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DeleteExpiredIndices indicates an expected call of DeleteExpiredIndices. -func (mr *MockTransactionMockRecorder) DeleteExpiredIndices(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteExpiredIndices", reflect.TypeOf((*MockTransaction)(nil).DeleteExpiredIndices), arg0, arg1) -} - -// DeleteSegmentRsv mocks base method. -func (m *MockTransaction) DeleteSegmentRsv(arg0 context.Context, arg1 *reservation.SegmentID) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteSegmentRsv", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteSegmentRsv indicates an expected call of DeleteSegmentRsv. -func (mr *MockTransactionMockRecorder) DeleteSegmentRsv(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSegmentRsv", reflect.TypeOf((*MockTransaction)(nil).DeleteSegmentRsv), arg0, arg1) -} - -// GetAllSegmentRsvs mocks base method. -func (m *MockTransaction) GetAllSegmentRsvs(arg0 context.Context) ([]*segment.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAllSegmentRsvs", arg0) - ret0, _ := ret[0].([]*segment.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetAllSegmentRsvs indicates an expected call of GetAllSegmentRsvs. -func (mr *MockTransactionMockRecorder) GetAllSegmentRsvs(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllSegmentRsvs", reflect.TypeOf((*MockTransaction)(nil).GetAllSegmentRsvs), arg0) -} - -// GetE2ERsvFromID mocks base method. -func (m *MockTransaction) GetE2ERsvFromID(arg0 context.Context, arg1 *reservation.E2EID) (*e2e.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetE2ERsvFromID", arg0, arg1) - ret0, _ := ret[0].(*e2e.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetE2ERsvFromID indicates an expected call of GetE2ERsvFromID. -func (mr *MockTransactionMockRecorder) GetE2ERsvFromID(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetE2ERsvFromID", reflect.TypeOf((*MockTransaction)(nil).GetE2ERsvFromID), arg0, arg1) -} - -// GetE2ERsvsOnSegRsv mocks base method. -func (m *MockTransaction) GetE2ERsvsOnSegRsv(arg0 context.Context, arg1 *reservation.SegmentID) ([]*e2e.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetE2ERsvsOnSegRsv", arg0, arg1) - ret0, _ := ret[0].([]*e2e.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetE2ERsvsOnSegRsv indicates an expected call of GetE2ERsvsOnSegRsv. -func (mr *MockTransactionMockRecorder) GetE2ERsvsOnSegRsv(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetE2ERsvsOnSegRsv", reflect.TypeOf((*MockTransaction)(nil).GetE2ERsvsOnSegRsv), arg0, arg1) -} - -// GetSegmentRsvFromID mocks base method. -func (m *MockTransaction) GetSegmentRsvFromID(arg0 context.Context, arg1 *reservation.SegmentID) (*segment.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSegmentRsvFromID", arg0, arg1) - ret0, _ := ret[0].(*segment.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSegmentRsvFromID indicates an expected call of GetSegmentRsvFromID. -func (mr *MockTransactionMockRecorder) GetSegmentRsvFromID(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSegmentRsvFromID", reflect.TypeOf((*MockTransaction)(nil).GetSegmentRsvFromID), arg0, arg1) -} - -// GetSegmentRsvFromPath mocks base method. -func (m *MockTransaction) GetSegmentRsvFromPath(arg0 context.Context, arg1 segment.ReservationTransparentPath) (*segment.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSegmentRsvFromPath", arg0, arg1) - ret0, _ := ret[0].(*segment.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSegmentRsvFromPath indicates an expected call of GetSegmentRsvFromPath. -func (mr *MockTransactionMockRecorder) GetSegmentRsvFromPath(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSegmentRsvFromPath", reflect.TypeOf((*MockTransaction)(nil).GetSegmentRsvFromPath), arg0, arg1) -} - -// GetSegmentRsvsFromIFPair mocks base method. -func (m *MockTransaction) GetSegmentRsvsFromIFPair(arg0 context.Context, arg1, arg2 *uint16) ([]*segment.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSegmentRsvsFromIFPair", arg0, arg1, arg2) - ret0, _ := ret[0].([]*segment.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSegmentRsvsFromIFPair indicates an expected call of GetSegmentRsvsFromIFPair. -func (mr *MockTransactionMockRecorder) GetSegmentRsvsFromIFPair(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSegmentRsvsFromIFPair", reflect.TypeOf((*MockTransaction)(nil).GetSegmentRsvsFromIFPair), arg0, arg1, arg2) -} - -// GetSegmentRsvsFromSrcDstIA mocks base method. -func (m *MockTransaction) GetSegmentRsvsFromSrcDstIA(arg0 context.Context, arg1, arg2 addr.IA) ([]*segment.Reservation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSegmentRsvsFromSrcDstIA", arg0, arg1, arg2) - ret0, _ := ret[0].([]*segment.Reservation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSegmentRsvsFromSrcDstIA indicates an expected call of GetSegmentRsvsFromSrcDstIA. -func (mr *MockTransactionMockRecorder) GetSegmentRsvsFromSrcDstIA(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSegmentRsvsFromSrcDstIA", reflect.TypeOf((*MockTransaction)(nil).GetSegmentRsvsFromSrcDstIA), arg0, arg1, arg2) -} - -// NewSegmentRsv mocks base method. -func (m *MockTransaction) NewSegmentRsv(arg0 context.Context, arg1 *segment.Reservation) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewSegmentRsv", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// NewSegmentRsv indicates an expected call of NewSegmentRsv. -func (mr *MockTransactionMockRecorder) NewSegmentRsv(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewSegmentRsv", reflect.TypeOf((*MockTransaction)(nil).NewSegmentRsv), arg0, arg1) -} - -// PersistE2ERsv mocks base method. -func (m *MockTransaction) PersistE2ERsv(arg0 context.Context, arg1 *e2e.Reservation) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PersistE2ERsv", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// PersistE2ERsv indicates an expected call of PersistE2ERsv. -func (mr *MockTransactionMockRecorder) PersistE2ERsv(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PersistE2ERsv", reflect.TypeOf((*MockTransaction)(nil).PersistE2ERsv), arg0, arg1) -} - -// PersistSegmentRsv mocks base method. -func (m *MockTransaction) PersistSegmentRsv(arg0 context.Context, arg1 *segment.Reservation) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PersistSegmentRsv", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// PersistSegmentRsv indicates an expected call of PersistSegmentRsv. -func (mr *MockTransactionMockRecorder) PersistSegmentRsv(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PersistSegmentRsv", reflect.TypeOf((*MockTransaction)(nil).PersistSegmentRsv), arg0, arg1) -} - -// Rollback mocks base method. -func (m *MockTransaction) Rollback() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Rollback") - ret0, _ := ret[0].(error) - return ret0 -} - -// Rollback indicates an expected call of Rollback. -func (mr *MockTransactionMockRecorder) Rollback() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rollback", reflect.TypeOf((*MockTransaction)(nil).Rollback)) -} diff --git a/control/colibri/reservationstorage/store.go b/control/colibri/reservationstorage/store.go deleted file mode 100644 index d8400a92a..000000000 --- a/control/colibri/reservationstorage/store.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 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 reservationstorage - -import ( - "context" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/control/colibri/reservation/e2e" - sgt "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/private/storage/cleaner" -) - -// Store is the interface to interact with the reservation store. -type Store interface { - AdmitSegmentReservation(ctx context.Context, req *sgt.SetupReq) ( - base.MessageWithPath, error) - ConfirmSegmentReservation(ctx context.Context, req *sgt.IndexConfirmationReq) ( - base.MessageWithPath, error) - CleanupSegmentReservation(ctx context.Context, req *sgt.CleanupReq) ( - base.MessageWithPath, error) - TearDownSegmentReservation(ctx context.Context, req *sgt.TeardownReq) ( - base.MessageWithPath, error) - AdmitE2EReservation(ctx context.Context, req e2e.SetupRequest) ( - base.MessageWithPath, error) - CleanupE2EReservation(ctx context.Context, req *e2e.CleanupReq) ( - base.MessageWithPath, error) - - DeleteExpiredIndices(ctx context.Context) (int, error) -} - -// TODO(juagargi) there is a number of functions missing: all regarding responses. - -// NewIndexCleaner creates a cleaner removing expired indices and reservations. -func NewIndexCleaner(s Store) *cleaner.Cleaner { - return cleaner.New(func(ctx context.Context) (int, error) { - return s.DeleteExpiredIndices(ctx) - }, "colibri") -} diff --git a/control/colibri/reservationstore/BUILD.bazel b/control/colibri/reservationstore/BUILD.bazel deleted file mode 100644 index 613b053c6..000000000 --- a/control/colibri/reservationstore/BUILD.bazel +++ /dev/null @@ -1,25 +0,0 @@ -load("//tools/lint:go.bzl", "go_library", "go_test") - -go_test( - name = "go_default_test", - srcs = ["store_test.go"], - embed = [":go_default_library"], - deps = ["//control/colibri/reservationstorage:go_default_library"], -) - -go_library( - name = "go_default_library", - srcs = ["store.go"], - importpath = "github.com/scionproto/scion/control/colibri/reservationstore", - visibility = ["//visibility:public"], - deps = [ - "//control/colibri/reservation:go_default_library", - "//control/colibri/reservation/e2e:go_default_library", - "//control/colibri/reservation/segment:go_default_library", - "//control/colibri/reservation/segment/admission:go_default_library", - "//control/colibri/reservationstorage:go_default_library", - "//control/colibri/reservationstorage/backend:go_default_library", - "//pkg/experimental/colibri/reservation:go_default_library", - "//pkg/private/serrors:go_default_library", - ], -) diff --git a/control/colibri/reservationstore/store.go b/control/colibri/reservationstore/store.go deleted file mode 100644 index 9b6a5bb14..000000000 --- a/control/colibri/reservationstore/store.go +++ /dev/null @@ -1,594 +0,0 @@ -// Copyright 2020 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 reservationstore - -import ( - "context" - "math" - "time" - - base "github.com/scionproto/scion/control/colibri/reservation" - "github.com/scionproto/scion/control/colibri/reservation/e2e" - "github.com/scionproto/scion/control/colibri/reservation/segment" - "github.com/scionproto/scion/control/colibri/reservation/segment/admission" - "github.com/scionproto/scion/control/colibri/reservationstorage" - "github.com/scionproto/scion/control/colibri/reservationstorage/backend" - "github.com/scionproto/scion/pkg/experimental/colibri/reservation" - "github.com/scionproto/scion/pkg/private/serrors" -) - -// Store is the reservation store. -type Store struct { - db backend.DB // aka reservation map - admitter admission.Admitter // the chosen admission entity -} - -var _ reservationstorage.Store = (*Store)(nil) - -// NewStore creates a new reservation store. -func NewStore(db backend.DB, admitter admission.Admitter) *Store { - return &Store{ - db: db, - admitter: admitter, - } -} - -// AdmitSegmentReservation receives a setup/renewal request to admit a segment reservation. -// It is expected that this AS is not the reservation initiator. -func (s *Store) AdmitSegmentReservation(ctx context.Context, req *segment.SetupReq) ( - base.MessageWithPath, error) { - - if err := s.validateAuthenticators(&req.RequestMetadata); err != nil { - return nil, serrors.WrapStr("error validating request", err, "id", req.ID) - } - if req.Path().IndexOfCurrentHop() != len(req.AllocTrail) { - return nil, serrors.New("inconsistent number of hops", - "len_alloctrail", len(req.AllocTrail), "hf_count", req.Path().IndexOfCurrentHop()) - } - - response, err := s.prepareFailureSegmentResp(&req.Request) - if err != nil { - return nil, serrors.WrapStr("cannot construct response", err, "id", req.ID) - } - failedResponse := &segment.ResponseSetupFailure{ - Response: *response, - FailedSetup: req, - } - - tx, err := s.db.BeginTransaction(ctx, nil) - if err != nil { - return failedResponse, serrors.WrapStr("cannot create transaction", err, - "id", req.ID) - } - defer tx.Rollback() - - rsv, err := tx.GetSegmentRsvFromID(ctx, &req.ID) - if err != nil { - return failedResponse, serrors.WrapStr("cannot obtain segment reservation", err, - "id", req.ID) - } - - if rsv != nil { - // renewal, ensure index is not used - index := rsv.Index(req.InfoField.Idx) - if index != nil { - return failedResponse, serrors.New("index from setup already in use", - "idx", req.InfoField.Idx, "id", req.ID) - } - } else { - // setup, create reservation and an index - rsv = segment.NewReservation() - rsv.ID = req.ID - err = tx.NewSegmentRsv(ctx, rsv) - if err != nil { - return failedResponse, serrors.WrapStr( - "unable to create a new segment reservation in db", err, - "id", req.ID) - } - } - req.Reservation = rsv - tok := &reservation.Token{InfoField: req.InfoField} - idx, err := rsv.NewIndexFromToken(tok, req.MinBW, req.MaxBW) - if err != nil { - return failedResponse, serrors.WrapStr("cannot create index from token", err, - "id", req.ID) - } - index := rsv.Index(idx) - - // checkpath type compatibility with end properties - if err := rsv.PathEndProps.ValidateWithPathType(rsv.PathType); err != nil { - return failedResponse, serrors.WrapStr("error validating end props and path type", err, - "id", req.ID) - } - // compute admission max BW - // TODO(juagargi) use the transaction also in the admitter - err = s.admitter.AdmitRsv(ctx, req) - if err != nil { - return failedResponse, serrors.WrapStr("segment not admitted", err, "id", req.ID, - "index", req.Index) - } - // admitted; the request contains already the value inside the "allocation beads" of the rsv - index.AllocBW = req.AllocTrail[len(req.AllocTrail)-1].AllocBW - - if err = tx.PersistSegmentRsv(ctx, rsv); err != nil { - return failedResponse, serrors.WrapStr("cannot persist segment reservation", err, - "id", req.ID) - } - if err := tx.Commit(); err != nil { - return failedResponse, serrors.WrapStr("cannot commit transaction", err, "id", req.ID) - } - - if req.IsLastAS() { - // TODO(juagargi) update token here - return &segment.ResponseSetupSuccess{ - Response: *morphSegmentResponseToSuccess(response), - Token: *index.Token, - }, nil - } - // TODO(juagargi) refactor function - return req, nil -} - -// ConfirmSegmentReservation changes the state of an index from temporary to confirmed. -func (s *Store) ConfirmSegmentReservation(ctx context.Context, req *segment.IndexConfirmationReq) ( - base.MessageWithPath, error) { - - if err := s.validateAuthenticators(&req.RequestMetadata); err != nil { - return nil, serrors.WrapStr("error validating request", err, "id", req.ID) - } - - response, err := s.prepareFailureSegmentResp(&req.Request) - if err != nil { - return nil, serrors.WrapStr("cannot construct response", err, "id", req.ID) - } - failedResponse := &segment.ResponseIndexConfirmationFailure{ - Response: *response, - ErrorCode: 1, // TODO(juagargi) specify error codes for every response - } - - tx, err := s.db.BeginTransaction(ctx, nil) - if err != nil { - return failedResponse, serrors.WrapStr("cannot create transaction", err, "id", req.ID) - } - defer tx.Rollback() - - rsv, err := tx.GetSegmentRsvFromID(ctx, &req.ID) - if err != nil { - return failedResponse, serrors.WrapStr("cannot obtain segment reservation", err, - "id", req.ID) - } - if err := rsv.SetIndexConfirmed(req.Index); err != nil { - return failedResponse, serrors.WrapStr("cannot set index to confirmed", err, - "id", req.ID) - } - if err = tx.PersistSegmentRsv(ctx, rsv); err != nil { - return failedResponse, serrors.WrapStr("cannot persist segment reservation", err, - "id", req.ID) - } - if err := tx.Commit(); err != nil { - return failedResponse, serrors.WrapStr("cannot commit transaction", err, - "id", req.ID) - } - if req.IsLastAS() { - return &segment.ResponseIndexConfirmationSuccess{ - Response: *morphSegmentResponseToSuccess(response), - }, nil - } - return req, nil -} - -// CleanupSegmentReservation deletes an index from a segment reservation. -func (s *Store) CleanupSegmentReservation(ctx context.Context, req *segment.CleanupReq) ( - base.MessageWithPath, error) { - - if err := s.validateAuthenticators(&req.RequestMetadata); err != nil { - return nil, serrors.WrapStr("error validating request", err, "id", req.ID) - } - - response, err := s.prepareFailureSegmentResp(&req.Request) - if err != nil { - return nil, serrors.WrapStr("cannot construct response", err, "id", req.ID) - } - failedResponse := &segment.ResponseCleanupFailure{ - Response: *response, - ErrorCode: 1, - } - - tx, err := s.db.BeginTransaction(ctx, nil) - if err != nil { - return failedResponse, serrors.WrapStr("cannot create transaction", err, "id", req.ID) - } - defer tx.Rollback() - - rsv, err := tx.GetSegmentRsvFromID(ctx, &req.ID) - if err != nil { - return failedResponse, serrors.WrapStr("cannot obtain segment reservation", err, - "id", req.ID) - } - if err := rsv.RemoveIndex(req.Index); err != nil { - return failedResponse, serrors.WrapStr("cannot delete segment reservation index", err, - "id", req.ID, "index", req.Index) - } - if err = tx.PersistSegmentRsv(ctx, rsv); err != nil { - return failedResponse, serrors.WrapStr("cannot persist segment reservation", err, - "id", req.ID) - } - if err := tx.Commit(); err != nil { - return failedResponse, serrors.WrapStr("cannot commit transaction", err, - "id", req.ID) - } - - if req.IsLastAS() { - return &segment.ResponseCleanupSuccess{ - Response: *morphSegmentResponseToSuccess(response), - }, nil - } - return req, nil -} - -// TearDownSegmentReservation removes a whole segment reservation. -func (s *Store) TearDownSegmentReservation(ctx context.Context, req *segment.TeardownReq) ( - base.MessageWithPath, error) { - - if err := s.validateAuthenticators(&req.RequestMetadata); err != nil { - return nil, serrors.WrapStr("error validating request", err, "id", req.ID) - } - - response, err := s.prepareFailureSegmentResp(&req.Request) - if err != nil { - return nil, serrors.WrapStr("cannot construct response", err, "id", req.ID) - } - failedResponse := &segment.ResponseTeardownFailure{ - Response: *response, - ErrorCode: 1, - } - - tx, err := s.db.BeginTransaction(ctx, nil) - if err != nil { - return failedResponse, serrors.WrapStr("cannot create transaction", err, "id", req.ID) - } - defer tx.Rollback() - - if err := tx.DeleteSegmentRsv(ctx, &req.ID); err != nil { - return failedResponse, serrors.WrapStr("cannot teardown reservation", err, - "id", req.ID) - } - if err := tx.Commit(); err != nil { - return failedResponse, serrors.WrapStr("cannot commit transaction", err, - "id", req.ID) - } - - if req.IsLastAS() { - return &segment.ResponseTeardownSuccess{ - Response: *morphSegmentResponseToSuccess(response), - }, nil - } - return req, nil -} - -// AdmitE2EReservation will atempt to admit an e2e reservation. -func (s *Store) AdmitE2EReservation(ctx context.Context, request e2e.SetupRequest) ( - base.MessageWithPath, error) { - - req := request.GetCommonSetupReq() - if err := s.validateAuthenticators(&req.RequestMetadata); err != nil { - return nil, serrors.WrapStr("error validating e2e request", err, "id", req.ID) - } - - response, err := s.prepareFailureE2EResp(&req.Request) - if err != nil { - return nil, serrors.WrapStr("cannot construct response", err, "id", req.ID) - } - var failedResponse base.MessageWithPath - failedResponse = &e2e.ResponseSetupFailure{ - Response: *response, - ErrorCode: 1, - MaxBWs: req.AllocationTrail, - } - - // sanity check: all successful requests are SetupReqSuccess. Failed ones are SetupReqFailure. - if request.IsSuccessful() { - if _, ok := request.(*e2e.SetupReqSuccess); !ok { - return failedResponse, serrors.New("logic error, successful request can be casted") - } - } else { - if _, ok := request.(*e2e.SetupReqFailure); !ok { - return failedResponse, serrors.New("logic error, failed request can be casted") - } - } - - if len(req.SegmentRsvs) == 0 || len(req.SegmentRsvs) > 3 { - return failedResponse, serrors.New("invalid number of segment reservations for an e2e one", - "count", len(req.SegmentRsvs)) - } - - tx, err := s.db.BeginTransaction(ctx, nil) - if err != nil { - return failedResponse, serrors.WrapStr("cannot create transaction", err, - "id", req.ID) - } - defer tx.Rollback() - - rsv, err := tx.GetE2ERsvFromID(ctx, &req.ID) - if err != nil { - return failedResponse, serrors.WrapStr("cannot obtain e2e reservation", err, - "id", req.ID) - } - - segRsvIDs := req.SegmentRsvIDsForThisAS() - if rsv != nil { - // renewal - if index := rsv.Index(req.Index); index != nil { - return failedResponse, serrors.New("already existing e2e index", "id", req.ID, - "idx", req.Index) - } - } else { - // new setup - rsv = &e2e.Reservation{ - ID: req.ID, - SegmentReservations: make([]*segment.Reservation, len(segRsvIDs)), - } - for i, id := range segRsvIDs { - r, err := tx.GetSegmentRsvFromID(ctx, &id) - if err != nil { - return failedResponse, serrors.WrapStr("cannot get segment rsv for e2e admission", - err, "e2e_id", req.ID, "seg_id", id) - } - rsv.SegmentReservations[i] = r - } - } - if len(rsv.SegmentReservations) == 0 { - return failedResponse, serrors.New("there is no segment rsv. associated to this e2e rsv.", - "id", req.ID, "idx", req.Index) - } - - idx, err := rsv.NewIndex(req.Timestamp) - if err != nil { - return failedResponse, serrors.WrapStr("cannot create index in e2e admission", err, - "e2e_id", req.ID) - } - index := rsv.Index(idx) - index.AllocBW = req.RequestedBW - if request.IsSuccessful() { - index.Token = &request.(*e2e.SetupReqSuccess).Token - } - - free, err := freeInSegRsv(ctx, tx, rsv.SegmentReservations[0]) - if err != nil { - return failedResponse, serrors.WrapStr("cannot compute free bw for e2e admission", err, - "e2e_id", rsv.ID) - } - free = free + rsv.AllocResv() // don't count this E2E request in the used BW - - if req.Transfer() { - // this AS must stitch two segment rsvs. according to the request - if len(segRsvIDs) == 1 { - return failedResponse, serrors.New("e2e setup request with transfer inconsistent", - "e2e_id", req.ID, "req_sgmt_rsvs_count", req.SegmentRsvASCount, - "trail_len", len(req.AllocationTrail)) - } - freeOutgoing, err := freeAfterTransfer(ctx, tx, rsv) - if err != nil { - return failedResponse, serrors.WrapStr("cannot compute transfer", err, "id", req.ID) - } - freeOutgoing += rsv.AllocResv() // do not count this rsv's BW - if free > freeOutgoing { - free = freeOutgoing - } - } - - if !request.IsSuccessful() || req.RequestedBW.ToKbps() > free { - maxWillingToAlloc := reservation.BWClsFromBW(free) - if req.Location() == e2e.Destination { - asAResponse := failedResponse.(*e2e.ResponseSetupFailure) - asAResponse.MaxBWs = append(asAResponse.MaxBWs, maxWillingToAlloc) - } else { - asARequest := &e2e.SetupReqFailure{ - SetupReq: *req, - ErrorCode: 1, - } - asARequest.AllocationTrail = append(asARequest.AllocationTrail, maxWillingToAlloc) - failedResponse = asARequest - } - return failedResponse, serrors.WrapStr("e2e not admitted", err, "id", req.ID, - "index", req.Index) - } - - // admitted so far - // TODO(juagargi) update token here - if err := tx.PersistE2ERsv(ctx, rsv); err != nil { - return failedResponse, serrors.WrapStr("cannot persist e2e reservation", err, - "id", req.ID) - } - - if err := tx.Commit(); err != nil { - return failedResponse, serrors.WrapStr("cannot commit transaction", err, "id", req.ID) - } - - var msg base.MessageWithPath - if req.Location() == e2e.Destination { - asAResponse := failedResponse.(*e2e.ResponseSetupFailure) - msg = &e2e.ResponseSetupSuccess{ - Response: *morphE2EResponseToSuccess(&asAResponse.Response), - Token: *index.Token, - } - } else { - msg = &e2e.SetupReqSuccess{ - SetupReq: *req, - Token: *index.Token, - } - } - return msg, nil -} - -// CleanupE2EReservation will remove an index from an e2e reservation. -func (s *Store) CleanupE2EReservation(ctx context.Context, req *e2e.CleanupReq) ( - base.MessageWithPath, error) { - - if err := s.validateAuthenticators(&req.RequestMetadata); err != nil { - return nil, serrors.WrapStr("error validating request", err, "id", req.ID) - } - - response, err := s.prepareFailureE2EResp(&req.Request) - if err != nil { - return nil, serrors.WrapStr("cannot construct response", err, "id", req.ID) - } - failedResponse := &e2e.ResponseCleanupFailure{ - Response: *response, - ErrorCode: 1, - } - - tx, err := s.db.BeginTransaction(ctx, nil) - if err != nil { - return failedResponse, serrors.WrapStr("cannot create transaction", err, "id", req.ID) - } - defer tx.Rollback() - - rsv, err := tx.GetE2ERsvFromID(ctx, &req.ID) - if err != nil { - return failedResponse, serrors.WrapStr("cannot obtain e2e reservation", err, - "id", req.ID) - } - if err := rsv.RemoveIndex(req.Index); err != nil { - return failedResponse, serrors.WrapStr("cannot delete e2e reservation index", err, - "id", req.ID, "index", req.Index) - } - if err := tx.PersistE2ERsv(ctx, rsv); err != nil { - return failedResponse, serrors.WrapStr("cannot persist e2e reservation", err, - "id", req.ID) - } - if err := tx.Commit(); err != nil { - return failedResponse, serrors.WrapStr("cannot commit transaction", err, - "id", req.ID) - } - - if req.IsLastAS() { - return &e2e.ResponseCleanupSuccess{ - Response: *morphE2EResponseToSuccess(response), - }, nil - } - - return req, nil -} - -// DeleteExpiredIndices will just call the DB's method to delete the expired indices. -func (s *Store) DeleteExpiredIndices(ctx context.Context) (int, error) { - return s.db.DeleteExpiredIndices(ctx, time.Now()) -} - -// validateAuthenticators checks that the authenticators are correct. -func (s *Store) validateAuthenticators(req *base.RequestMetadata) error { - // TODO(juagargi) validate request - // DRKey authentication of request (will be left undone for later) - return nil -} - -// prepareFailureSegmentResp will create a failure segment response, which -// is sent in the reverse path that the request had. -func (s *Store) prepareFailureSegmentResp(req *segment.Request) (*segment.Response, error) { - revPath := req.Path().Copy() - if err := revPath.Reverse(); err != nil { - return nil, serrors.WrapStr("cannot reverse path for response", err) - } - - response, err := segment.NewResponse(time.Now(), &req.ID, req.Index, revPath, - false, uint8(req.Path().IndexOfCurrentHop())) - if err != nil { - return nil, serrors.WrapStr("cannot construct segment response", err) - } - return response, nil -} - -// prepareFailureE2EResp will create a failure e2e response, which -// is sent in the reverse path that the request had. -func (s *Store) prepareFailureE2EResp(req *e2e.Request) (*e2e.Response, error) { - revPath := req.Path().Copy() - if err := revPath.Reverse(); err != nil { - return nil, serrors.WrapStr("cannot reverse path for response", err) - } - - response, err := e2e.NewResponse(time.Now(), &req.ID, req.Index, revPath, - false, uint8(req.Path().IndexOfCurrentHop())) - if err != nil { - return nil, serrors.WrapStr("cannot construct e2e response", err) - } - return response, nil -} - -func morphSegmentResponseToSuccess(resp *segment.Response) *segment.Response { - resp.Accepted = true - resp.FailedHop = 0 - return resp -} - -func morphE2EResponseToSuccess(resp *e2e.Response) *e2e.Response { - resp.Accepted = true - resp.FailedHop = 0 - return resp -} - -func sumAllBW(rsvs []*e2e.Reservation) uint64 { - var accum uint64 - for _, r := range rsvs { - accum += r.AllocResv() - } - return accum -} - -func freeInSegRsv(ctx context.Context, tx backend.Transaction, segRsv *segment.Reservation) ( - uint64, error) { - - rsvs, err := tx.GetE2ERsvsOnSegRsv(ctx, &segRsv.ID) - if err != nil { - return 0, serrors.WrapStr("cannot obtain e2e reservations to compute free bw", - err, "segment_id", segRsv.ID) - } - free := float64(segRsv.ActiveIndex().AllocBW.ToKbps())*float64(segRsv.TrafficSplit) - - float64(sumAllBW(rsvs)) - return uint64(free), nil -} - -// max bw in egress interface of the transfer AS -func freeAfterTransfer(ctx context.Context, tx backend.Transaction, rsv *e2e.Reservation) ( - uint64, error) { - - seg1 := rsv.SegmentReservations[0] - seg2 := rsv.SegmentReservations[1] - if seg1.PathType == reservation.CorePath && seg2.PathType == reservation.DownPath { - // as if no transfer - return math.MaxUint64, nil - } - // get all seg rsvs with this AS as destination, AND transfer flag set - rsvs, err := tx.GetAllSegmentRsvs(ctx) - if err != nil { - return 0, err - } - var total uint64 - for _, r := range rsvs { - if r.Egress == 0 && r.PathEndProps&reservation.EndTransfer != 0 { - total += r.ActiveIndex().AllocBW.ToKbps() - } - } - ratio := float64(seg1.ActiveIndex().AllocBW.ToKbps()) / float64(total) - // effectiveE2eTraffic is the minimum BW that e2e rsvs can use - effectiveE2eTraffic := float64(seg2.ActiveIndex().AllocBW.ToKbps()) * ratio - e2es, err := tx.GetE2ERsvsOnSegRsv(ctx, &seg2.ID) - if err != nil { - return 0, err - } - total = sumAllBW(e2es) - // the available BW for this e2e rsv is the effective minus the already used - return uint64(effectiveE2eTraffic) - total, nil -} diff --git a/control/colibri/reservationstore/store_test.go b/control/colibri/reservationstore/store_test.go deleted file mode 100644 index 71b8794ea..000000000 --- a/control/colibri/reservationstore/store_test.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 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 reservationstore - -import ( - "testing" - - "github.com/scionproto/scion/control/colibri/reservationstorage" -) - -func TestStore(t *testing.T) { - var s reservationstorage.Store = &Store{} - _ = s -} diff --git a/doc/dev/design/ColibriService.md b/doc/dev/design/ColibriService.md index 0401f592b..cf0470504 100644 --- a/doc/dev/design/ColibriService.md +++ b/doc/dev/design/ColibriService.md @@ -2,9 +2,18 @@ * Author: Juan A. García Pardo * Last updated: 2020-07-08 -* Status: **experimental**, prototype being developed in [netsec-ethz/scion:scionlab](https://github.com/netsec-ethz/scion/tree/scionlab) +* Status: **outdated**. + Prototype was developed in [netsec-ethz/scion:scionlab](https://github.com/netsec-ethz/scion/tree/scionlab) + ([commit permalink](https://github.com/netsec-ethz/scion/commit/37a556a4bc494a93fe8294ed77b6f2c9b6192746)), + to be replaced with new approach for QoS system. * Discussion at: [#3653](https://github.com/scionproto/scion/issues/3653), [#3794](https://github.com/scionproto/scion/issues/3794) +--- +⚠️ **NOTE** ⚠️
+Outdated contents! This document is kept for historical purpose. + +--- + ## Abstract This document specifies the design of the COLIBRI service. It aims for correctness not completeness, diff --git a/doc/dev/design/index.rst b/doc/dev/design/index.rst index bbc2d2954..d2a249802 100644 --- a/doc/dev/design/index.rst +++ b/doc/dev/design/index.rst @@ -39,7 +39,6 @@ Active uri grpc - ColibriService BorderRouter .. _design-docs-completed: @@ -63,6 +62,7 @@ Outdated BeaconService PathService forwarding-key-rollover + ColibriService .. seealso:: diff --git a/nogo.json b/nogo.json index 8ab55bd98..2724a13b9 100644 --- a/nogo.json +++ b/nogo.json @@ -206,7 +206,6 @@ "org_golang_x_crypto/ed25519/internal/edwards25519": "", "com_github_vishvananda_netlink/nl": "", "com_github_deepmap_oapi_codegen/pkg/codegen": "", - "control/colibri/reservation/e2e/request_test.go": "", "com_github_bazelbuild_buildtools": "" } } diff --git a/pkg/experimental/colibri/reservation/BUILD.bazel b/pkg/experimental/colibri/reservation/BUILD.bazel deleted file mode 100644 index 622702e0c..000000000 --- a/pkg/experimental/colibri/reservation/BUILD.bazel +++ /dev/null @@ -1,23 +0,0 @@ -load("//tools/lint:go.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["types.go"], - importpath = "github.com/scionproto/scion/pkg/experimental/colibri/reservation", - visibility = ["//visibility:public"], - deps = [ - "//pkg/addr:go_default_library", - "//pkg/private/serrors:go_default_library", - "//pkg/private/util:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["types_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/private/xtest:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) diff --git a/pkg/experimental/colibri/reservation/types.go b/pkg/experimental/colibri/reservation/types.go deleted file mode 100644 index 5166dfc13..000000000 --- a/pkg/experimental/colibri/reservation/types.go +++ /dev/null @@ -1,584 +0,0 @@ -// 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 reservation - -import ( - "encoding/binary" - "encoding/hex" - "fmt" - "io" - "math" - "time" - - "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/private/serrors" - "github.com/scionproto/scion/pkg/private/util" -) - -// SegmentID identifies a COLIBRI segment reservation. The suffix differentiates -// reservations for the same AS. -type SegmentID struct { - ASID addr.AS - Suffix [4]byte -} - -var _ io.Reader = (*SegmentID)(nil) - -const SegmentIDLen = 10 - -// NewSegmentID returns a new SegmentID -func NewSegmentID(AS addr.AS, suffix []byte) (*SegmentID, error) { - if len(suffix) != 4 { - return nil, serrors.New("wrong suffix length, should be 4", "actual_len", len(suffix)) - } - id := SegmentID{ASID: AS} - copy(id.Suffix[:], suffix) - return &id, nil -} - -// SegmentIDFromRawBuffers constructs a SegmentID from two separate buffers. -func SegmentIDFromRawBuffers(ASID, suffix []byte) (*SegmentID, error) { - if len(ASID) < 6 || len(suffix) < 4 { - return nil, serrors.New("buffers too small", "length_ASID", len(ASID), - "length_suffix", len(suffix)) - } - return NewSegmentID(addr.AS(binary.BigEndian.Uint64(append([]byte{0, 0}, ASID[:6]...))), - suffix[:4]) -} - -// SegmentIDFromRaw constructs a SegmentID parsing a raw buffer. -func SegmentIDFromRaw(raw []byte) ( - *SegmentID, error) { - - if len(raw) < SegmentIDLen { - return nil, serrors.New("buffer too small", "actual", len(raw), - "min", SegmentIDLen) - } - return SegmentIDFromRawBuffers(raw[:6], raw[6:]) -} - -// Read serializes this SegmentID into the buffer. -func (id *SegmentID) Read(raw []byte) (int, error) { - if len(raw) < SegmentIDLen { - return 0, serrors.New("buffer too small", "actual", len(raw), "min", SegmentIDLen) - } - auxBuff := make([]byte, 8) - binary.BigEndian.PutUint64(auxBuff, uint64(id.ASID)) - copy(raw, auxBuff[2:8]) - copy(raw[6:], id.Suffix[:]) - return SegmentIDLen, nil -} - -// ToRaw calls Read and returns a new allocated buffer with the ID serialized. -func (id *SegmentID) ToRaw() []byte { - buf := make([]byte, SegmentIDLen) - _, _ = id.Read(buf) // safely ignore errors as they can only come from buffer size - return buf -} - -func (id *SegmentID) String() string { - return fmt.Sprintf("%s-%x", id.ASID, id.Suffix) -} - -// E2EID identifies a COLIBRI E2E reservation. The suffix is different for each -// reservation for any given AS. -type E2EID struct { - ASID addr.AS - Suffix [10]byte -} - -const E2EIDLen = 16 - -var _ io.Reader = (*E2EID)(nil) - -// NewE2EID returns a new E2EID -func NewE2EID(AS addr.AS, suffix []byte) (*E2EID, error) { - if len(suffix) != 10 { - return nil, serrors.New("wrong suffix length, should be 10", "actual_len", len(suffix)) - } - id := E2EID{ASID: AS} - copy(id.Suffix[:], suffix) - return &id, nil -} - -// E2EIDFromRawBuffers constructs a E2DID from two separate buffers. -func E2EIDFromRawBuffers(ASID, suffix []byte) (*E2EID, error) { - if len(ASID) < 6 || len(suffix) < 10 { - return nil, serrors.New("buffers too small", "length_ASID", len(ASID), - "length_suffix", len(suffix)) - } - return NewE2EID(addr.AS(binary.BigEndian.Uint64(append([]byte{0, 0}, ASID[:6]...))), - suffix[:10]) -} - -// E2EIDFromRaw constructs an E2EID parsing a buffer. -func E2EIDFromRaw(raw []byte) (*E2EID, error) { - if len(raw) < E2EIDLen { - return nil, serrors.New("buffer too small", "actual", len(raw), "min", E2EIDLen) - } - return E2EIDFromRawBuffers(raw[:6], raw[6:]) -} - -// Read serializes this E2EID into the buffer. -func (id *E2EID) Read(raw []byte) (int, error) { - if len(raw) < E2EIDLen { - return 0, serrors.New("buffer too small", "actual", len(raw), "min", E2EIDLen) - } - auxBuff := make([]byte, 8) - binary.BigEndian.PutUint64(auxBuff, uint64(id.ASID)) - copy(raw, auxBuff[2:8]) - copy(raw[6:], id.Suffix[:]) - return E2EIDLen, nil -} - -// ToRaw calls Read and returns a new allocated buffer with the ID serialized. -func (id *E2EID) ToRaw() []byte { - buf := make([]byte, E2EIDLen) - _, _ = id.Read(buf) // safely ignore errors as they can only come from buffer size - return buf -} - -// Tick represents a slice of time of 4 seconds. -type Tick uint32 - -// TickFromTime returns the tick for a given time. -func TickFromTime(t time.Time) Tick { - return Tick(util.TimeToSecs(t) / 4) -} - -func (t Tick) ToTime() time.Time { - return util.SecsToTime(uint32(t) * 4) -} - -// BWCls is the bandwidth class. bandwidth = 16 * sqrt(2^(BWCls - 1)). 0 <= bwcls <= 63 kbps. -type BWCls uint8 - -// BWClsFromBW constructs a BWCls from the bandwidth. Given that -// bandwidth = 16 * sqrt(2^(BWCls - 1)) -// where bandwidth is kbps. We then have -// BWCls = 2 * log2( bandwidth/16 ) + 1 -// The value of BWCls will be the ceiling of the previous expression. -func BWClsFromBW(bwKbps uint64) BWCls { - cls := 2*math.Log2(float64(bwKbps)/16) + 1 - cls = math.Min(cls, 63) - return BWCls(math.Ceil(cls)) -} - -// Validate will return an error for invalid values. -func (b BWCls) Validate() error { - if b > 63 { - return serrors.New("invalid BWClass value", "bw_cls", b) - } - return nil -} - -// ToKbps returns the kilobits per second this BWCls represents. -func (b BWCls) ToKbps() uint64 { - return uint64(16 * math.Sqrt(math.Pow(2, float64(b)-1))) -} - -// MaxBWCls returns the maximum of two BWCls. -func MaxBWCls(a, b BWCls) BWCls { - if a > b { - return a - } - return b -} - -// MinBWCls returns the minimum of two BWCls. -func MinBWCls(a, b BWCls) BWCls { - if a < b { - return a - } - return b -} - -// SplitCls is the traffic split parameter. split = sqrt(2^c). The split divides the bandwidth -// in control traffic (BW * split) and end to end traffic (BW * (1-s)). 0 <= splitCls <= 256 . -type SplitCls uint8 - -// RLC Request Latency Class. latency = 2^rlc miliseconds. 0 <= rlc <= 63 -type RLC uint8 - -// Validate will return an error for invalid values. -func (c RLC) Validate() error { - if c > 63 { - return serrors.New("invalid BWClass", "bw_cls", c) - } - return nil -} - -// IndexNumber is a 4 bit index for a reservation. -type IndexNumber uint8 - -// Validate will return an error for invalid values. -func (i IndexNumber) Validate() error { - if i >= 1<<4 { - return serrors.New("invalid IndexNumber", "value", i) - } - return nil -} - -func (i IndexNumber) Add(other IndexNumber) IndexNumber { - return (i + other) % 16 -} - -func (i IndexNumber) Sub(other IndexNumber) IndexNumber { - return (i - other) % 16 -} - -// PathType specifies which type of COLIBRI path this segment reservation or request refers to. -type PathType uint8 - -// the different COLIBRI path types. -const ( - UnknownPath PathType = iota - DownPath - UpPath - PeeringDownPath - PeeringUpPath - E2EPath - CorePath -) - -// Validate will return an error for invalid values. -func (pt PathType) Validate() error { - if pt == UnknownPath || pt > CorePath { - return serrors.New("invalid path type", "path_type", pt) - } - return nil -} - -// InfoField is used in the reservation token and segment request data. -// 0B 1 2 3 4 5 6 7 -// +--------+--------+--------+--------+--------+--------+--------+--------+ -// | Expiration time (4B) | BwCls | RTT Cls|Idx|Type| padding| -// +--------+--------+--------+--------+--------+--------+--------+--------+ -// -// The bandwidth class (BwCls) indicates the reserved bandwidth in an active -// reservation. In a steady request, it indicates the minimal bandwidth class -// reserved so far. In a ephemeral request, it indicates the bandwidth class -// that the source end host is seeking to reserve. -// -// The round trip class (RTT Cls) allows for more granular control in the -// pending request garbage collection. -// -// The reservation index (Idx) is used to allow for multiple overlapping -// reservations within a single path, which enables renewal and changing the -// bandwidth requested. -// -// Type indicates which path type of the reservation. -type InfoField struct { - ExpirationTick Tick - BWCls BWCls - RLC RLC - Idx IndexNumber - PathType PathType -} - -// InfoFieldLen is the length in bytes of the InfoField. -const InfoFieldLen = 8 - -var _ io.Reader = (*InfoField)(nil) - -// Validate will return an error for invalid values. -func (f *InfoField) Validate() error { - if err := f.BWCls.Validate(); err != nil { - return err - } - if err := f.RLC.Validate(); err != nil { - return err - } - if err := f.Idx.Validate(); err != nil { - return err - } - if err := f.PathType.Validate(); err != nil { - return err - } - - return nil -} - -// InfoFieldFromRaw builds an InfoField from the InfoFieldLen bytes buffer. -func InfoFieldFromRaw(raw []byte) (*InfoField, error) { - if len(raw) < InfoFieldLen { - return nil, serrors.New("buffer too small", "min_size", InfoFieldLen, - "current_size", len(raw)) - } - info := InfoField{ - ExpirationTick: Tick(binary.BigEndian.Uint32(raw[:4])), - BWCls: BWCls(raw[4]), - RLC: RLC(raw[5]), - Idx: IndexNumber(raw[6]) >> 4, - PathType: PathType(raw[6]) & 0x7, - } - if err := info.Validate(); err != nil { - return nil, err - } - return &info, nil -} - -// Read serializes this InfoField into a sequence of InfoFieldLen bytes. -func (f *InfoField) Read(b []byte) (int, error) { - if len(b) < InfoFieldLen { - return 0, serrors.New("buffer too small", "min_size", InfoFieldLen, - "current_size", len(b)) - } - binary.BigEndian.PutUint32(b[:4], uint32(f.ExpirationTick)) - b[4] = byte(f.BWCls) - b[5] = byte(f.RLC) - b[6] = byte(f.Idx<<4) | uint8(f.PathType) - b[7] = 0 // b[7] is padding - return InfoFieldLen, nil -} - -// ToRaw returns the serial representation of the InfoField. -func (f *InfoField) ToRaw() []byte { - var buff []byte = nil - if f != nil { - buff = make([]byte, InfoFieldLen) - _, _ = f.Read(buff) // safely ignore errors as they can only come from buffer size - } - return buff -} - -// PathEndProps represent the zero or more properties a COLIBRI path can have at both ends. -type PathEndProps uint8 - -// The only current properties are "Local" (can be used to create e2e rsvs) and "Transfer" (can be -// stiched together with another segment reservation). The first 4 bits encode the properties -// of the "Start" AS, and the last 4 bits encode those of the "End" AS. -const ( - StartLocal PathEndProps = 0x10 - StartTransfer PathEndProps = 0x20 - EndLocal PathEndProps = 0x01 - EndTransfer PathEndProps = 0x02 -) - -// Validate will return an error for invalid values. -func (pep PathEndProps) Validate() error { - if pep&0x0F > 0x03 { - return serrors.New("invalid path end properties (@End)", "path_end_props", pep) - } - if pep>>4 > 0x03 { - return serrors.New("invalid path end properties (@Start)", "path_end_props", pep) - } - return nil -} - -// ValidateWithPathType checks the validity of the properties when in a path of the specified type. -func (pep PathEndProps) ValidateWithPathType(pt PathType) error { - if err := pep.Validate(); err != nil { - return err - } - var invalid bool - s := pep & 0xF0 - e := pep & 0x0F - switch pt { - case CorePath: - if s == 0 { - invalid = true - } - case UpPath: - if s != StartLocal { - invalid = true - } - case DownPath: - if e != EndLocal { - invalid = true - } - case PeeringUpPath: - if s != StartLocal || e == 0 { - invalid = true - } - case PeeringDownPath: - if e != EndLocal || s == 0 { - invalid = true - } - } - if invalid { - return serrors.New("invalid combination of path end properties and path type", - "end_properties", hex.EncodeToString([]byte{byte(pep)}), "path_type", pt) - } - return nil -} - -func NewPathEndProps(startLocal, startTransfer, endLocal, endTransfer bool) PathEndProps { - var props PathEndProps - if startLocal { - props |= StartLocal - } - if startTransfer { - props |= StartTransfer - } - if endLocal { - props |= EndLocal - } - if endTransfer { - props |= EndTransfer - } - return props -} - -// AllocationBead represents an allocation resolved in an AS for a given reservation. -// It is used in an array to represent the allocation trail that happened for a reservation. -type AllocationBead struct { - AllocBW BWCls - MaxBW BWCls -} - -type AllocationBeads []AllocationBead - -// MinMax returns the minimum of all the max BW in the AllocationBeads. -func (bs AllocationBeads) MinMax() BWCls { - if len(bs) == 0 { - return 0 - } - var min BWCls = math.MaxUint8 - for _, b := range bs { - if b.MaxBW < min { - min = b.MaxBW - } - } - return min -} - -// HopField is a COLIBRI HopField. -// TODO(juagargi) move to slayers -type HopField struct { - Ingress uint16 - Egress uint16 - Mac [4]byte -} - -const HopFieldLen = 8 - -var _ io.Reader = (*HopField)(nil) - -// HopFieldFromRaw builds a HopField from a raw buffer. -func HopFieldFromRaw(raw []byte) (*HopField, error) { - if len(raw) < HopFieldLen { - return nil, serrors.New("buffer too small for HopField", "min_size", HopFieldLen, - "current_size", len(raw)) - } - hf := HopField{ - Ingress: binary.BigEndian.Uint16(raw[:2]), - Egress: binary.BigEndian.Uint16(raw[2:4]), - } - copy(hf.Mac[:], raw[4:8]) - return &hf, nil -} - -// Read serializes this HopField into the buffer. -func (hf *HopField) Read(b []byte) (int, error) { - if len(b) < HopFieldLen { - return 0, serrors.New("buffer too small for HopField", "min_size", HopFieldLen, - "current_size", len(b)) - } - binary.BigEndian.PutUint16(b[:2], hf.Ingress) - binary.BigEndian.PutUint16(b[2:4], hf.Egress) - copy(b[4:], hf.Mac[:]) - return HopFieldLen, nil -} - -// ToRaw returns the serial representation of the HopField. -func (hf *HopField) ToRaw() []byte { - buff := make([]byte, HopFieldLen) - _, _ = hf.Read(buff) // discard returned values - return buff -} - -// Token is used in the data plane to forward COLIBRI packets. -type Token struct { - InfoField - HopFields []HopField -} - -var _ io.Reader = (*Token)(nil) - -// Validate will return an error for invalid values. It will not check the hop fields' validity. -func (t *Token) Validate() error { - if len(t.HopFields) == 0 { - return serrors.New("token without hop fields") - } - return t.InfoField.Validate() -} - -// TokenFromRaw builds a Token from the passed bytes buffer. -func TokenFromRaw(raw []byte) (*Token, error) { - if raw == nil { - return nil, nil - } - rawHFs := len(raw) - InfoFieldLen - if rawHFs < 0 || rawHFs%HopFieldLen != 0 { - return nil, serrors.New("buffer too small for Token", "min_size", InfoFieldLen, - "current_size", len(raw)) - } - numHFs := rawHFs / HopFieldLen - inf, err := InfoFieldFromRaw(raw[:InfoFieldLen]) - if err != nil { - return nil, err - } - t := Token{ - InfoField: *inf, - } - if numHFs > 0 { - t.HopFields = make([]HopField, numHFs) - } - for i := 0; i < numHFs; i++ { - offset := InfoFieldLen + i*HopFieldLen - hf, err := HopFieldFromRaw(raw[offset : offset+HopFieldLen]) - if err != nil { - return nil, err - } - t.HopFields[i] = *hf - } - return &t, nil -} - -// Len returns the number of bytes of this token if serialized. -func (t *Token) Len() int { - if t == nil { - return 0 - } - return InfoFieldLen + len(t.HopFields)*HopFieldLen -} - -// Read serializes this Token to the passed buffer. -func (t *Token) Read(b []byte) (int, error) { - length := t.Len() - if len(b) < length { - return 0, serrors.New("buffer too small", "min_size", length, "current_size", len(b)) - } - offset, err := t.InfoField.Read(b[:InfoFieldLen]) - if err != nil { - return 0, err - } - for i := 0; i < len(t.HopFields); i++ { - _, _ = t.HopFields[i].Read(b[offset : offset+HopFieldLen]) - offset += HopFieldLen - } - return offset, nil -} - -// ToRaw returns the serial representation of the Token. -func (t *Token) ToRaw() []byte { - var buff []byte = nil - if t != nil { - buff = make([]byte, t.Len()) - _, _ = t.Read(buff) // safely ignore errors as they can only come from buffer size - } - return buff -} diff --git a/pkg/experimental/colibri/reservation/types_test.go b/pkg/experimental/colibri/reservation/types_test.go deleted file mode 100644 index df4969af6..000000000 --- a/pkg/experimental/colibri/reservation/types_test.go +++ /dev/null @@ -1,515 +0,0 @@ -// 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 reservation - -import ( - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/pkg/private/xtest" -) - -func TestSegmentIDFromRaw(t *testing.T) { - id, err := SegmentIDFromRaw(xtest.MustParseHexString("ffaa00001101facecafe")) - require.NoError(t, err) - require.Equal(t, xtest.MustParseAS("ffaa:0:1101"), id.ASID) - require.Equal(t, xtest.MustParseHexString("facecafe"), id.Suffix[:]) -} - -func TestSegmentIDRead(t *testing.T) { - reference := SegmentID{ - ASID: xtest.MustParseAS("ffaa:0:1101"), - } - copy(reference.Suffix[:], xtest.MustParseHexString("facecafe")) - raw := make([]byte, SegmentIDLen) - n, err := reference.Read(raw) - require.NoError(t, err) - require.Equal(t, SegmentIDLen, n) - require.Equal(t, xtest.MustParseHexString("ffaa00001101facecafe"), raw) -} - -func TestSegmentIDString(t *testing.T) { - cases := []struct { - ID SegmentID - Str string - }{ - {ID: mustParseSegmentID("ff0000001101facecafe"), Str: "ff00:0:1101-facecafe"}, - {ID: mustParseSegmentID("ff000000110100000000"), Str: "ff00:0:1101-00000000"}, - } - for i, c := range cases { - name := fmt.Sprintf("case %d", i) - t.Run(name, func(t *testing.T) { - c := c - t.Parallel() - require.Equal(t, c.Str, c.ID.String()) - }) - } -} - -func TestE2EIDFromRaw(t *testing.T) { - raw := xtest.MustParseHexString("ffaa00001101facecafedeadbeeff00d") - id, err := E2EIDFromRaw(raw) - require.NoError(t, err) - require.Equal(t, xtest.MustParseAS("ffaa:0:1101"), id.ASID) - require.Equal(t, xtest.MustParseHexString("facecafedeadbeeff00d"), id.Suffix[:]) -} - -func TestE2EIDRead(t *testing.T) { - reference := E2EID{ - ASID: xtest.MustParseAS("ffaa:0:1101"), - } - copy(reference.Suffix[:], xtest.MustParseHexString("facecafedeadbeeff00d")) - raw := make([]byte, E2EIDLen) - n, err := reference.Read(raw) - require.NoError(t, err) - require.Equal(t, E2EIDLen, n) - require.Equal(t, xtest.MustParseHexString("ffaa00001101facecafedeadbeeff00d"), raw) -} - -func TestTickFromTime(t *testing.T) { - require.Equal(t, Tick(0), TickFromTime(time.Unix(0, 0))) - require.Equal(t, Tick(0), TickFromTime(time.Unix(3, 999999))) - require.Equal(t, Tick(1), TickFromTime(time.Unix(4, 0))) -} - -func TestTickToTime(t *testing.T) { - require.Equal(t, time.Unix(0, 0), Tick(0).ToTime()) - require.Equal(t, time.Unix(4, 0), Tick(1).ToTime()) - require.Equal(t, time.Unix(0, 0), TickFromTime(time.Unix(0, 0)).ToTime()) - require.Equal(t, time.Unix(0, 0), TickFromTime(time.Unix(3, 999999)).ToTime()) - require.Equal(t, time.Unix(4, 0), TickFromTime(time.Unix(4, 0)).ToTime()) -} - -func TestValidateBWCls(t *testing.T) { - for i := 0; i < 64; i++ { - c := BWCls(i) - err := c.Validate() - require.NoError(t, err) - } - c := BWCls(64) - err := c.Validate() - require.Error(t, err) -} - -func TestBWClsToKbps(t *testing.T) { - cases := map[BWCls]uint64{ - 0: 11, - 1: 16, - 2: 22, - 5: 64, - 13: 1024, - 63: 32 * 1024 * 1024 * 1024, // 32 TBps - } - for cls, bw := range cases { - name := fmt.Sprintf("case for %d", cls) - t.Run(name, func(t *testing.T) { - cls := cls - bw := bw - t.Parallel() - require.Equal(t, bw, cls.ToKbps()) - }) - } -} - -func TestBWClsFromBW(t *testing.T) { - cases := map[uint64]BWCls{ - 0: 0, - 16: 1, - 22: 2, - 64: 5, - 1024: 13, - 32 * 1024 * 1024 * 1024: 63, - 21: 2, - 4096: 17, - 4000: 17, - 4097: 18, - } - for bw, cls := range cases { - name := fmt.Sprintf("case for %d", bw) - t.Run(name, func(t *testing.T) { - bw := bw - cls := cls - t.Parallel() - require.Equal(t, cls, BWClsFromBW(bw)) - }) - } -} - -func TestMaxBWCls(t *testing.T) { - cases := []struct{ a, b, max BWCls }{ - {a: 1, b: 1, max: 1}, - {a: 0, b: 1, max: 1}, - {a: 255, b: 1, max: 255}, - } - for i, c := range cases { - name := fmt.Sprintf("case %d", i) - t.Run(name, func(t *testing.T) { - c := c - t.Parallel() - require.Equal(t, c.max, MaxBWCls(c.a, c.b)) - }) - } -} - -func TestMinBWCls(t *testing.T) { - cases := []struct{ a, b, min BWCls }{ - {a: 1, b: 1, min: 1}, - {a: 0, b: 1, min: 0}, - {a: 255, b: 0, min: 0}, - } - for i, c := range cases { - name := fmt.Sprintf("case %d", i) - t.Run(name, func(t *testing.T) { - c := c - t.Parallel() - require.Equal(t, c.min, MinBWCls(c.a, c.b)) - }) - } -} - -func TestValidateRLC(t *testing.T) { - for i := 0; i < 64; i++ { - c := RLC(i) - err := c.Validate() - require.NoError(t, err) - } - c := RLC(64) - err := c.Validate() - require.Error(t, err) -} - -func TestValidateIndexNumber(t *testing.T) { - for i := 0; i < 16; i++ { - idx := IndexNumber(i) - err := idx.Validate() - require.NoError(t, err) - } - idx := IndexNumber(16) - err := idx.Validate() - require.Error(t, err) -} - -func TestIndexNumberArithmetic(t *testing.T) { - var idx IndexNumber = 1 - x := idx.Add(IndexNumber(15)) - require.Equal(t, IndexNumber(0), x) - x = idx.Sub(IndexNumber(2)) - require.Equal(t, IndexNumber(15), x) - // distance from 2 to 0 = 0 - 2 = 14 mod 16 - x = IndexNumber(2) - distance := IndexNumber(0).Sub(x) - require.Equal(t, IndexNumber(14), distance) - // distance from 2 to 4 - distance = IndexNumber(4).Sub(x) - require.Equal(t, IndexNumber(2), distance) -} - -func TestValidatePathType(t *testing.T) { - validTypes := []PathType{ - DownPath, - UpPath, - PeeringDownPath, - PeeringUpPath, - E2EPath, - CorePath, - } - for _, vt := range validTypes { - err := vt.Validate() - require.NoError(t, err) - } - err := UnknownPath.Validate() - require.Error(t, err) - - pt := CorePath + 1 - err = pt.Validate() - require.Error(t, err) -} - -func TestValidateInfoField(t *testing.T) { - infoField := InfoField{ - ExpirationTick: 0, - BWCls: 0, - RLC: 0, - Idx: 0, - PathType: CorePath, - } - err := infoField.Validate() - require.NoError(t, err) - - otherIF := infoField - otherIF.BWCls = 64 - err = otherIF.Validate() - require.Error(t, err) - - otherIF = infoField - otherIF.RLC = 64 - err = otherIF.Validate() - require.Error(t, err) - - otherIF = infoField - otherIF.Idx = 16 - err = otherIF.Validate() - require.Error(t, err) - - otherIF = infoField - otherIF.PathType = CorePath + 1 - err = otherIF.Validate() - require.Error(t, err) -} - -func TestInfoFieldFromRaw(t *testing.T) { - reference := newInfoField() - rawReference := newInfoFieldRaw() - info, err := InfoFieldFromRaw(rawReference) - require.NoError(t, err) - require.Equal(t, reference, *info) -} - -func TestInfoFieldRead(t *testing.T) { - reference := newInfoField() - rawReference := newInfoFieldRaw() - raw := make([]byte, InfoFieldLen) - // pollute the buffer with garbage - for i := 0; i < InfoFieldLen; i++ { - raw[i] = byte(i % 256) - } - n, err := reference.Read(raw) - require.NoError(t, err) - require.Equal(t, InfoFieldLen, n) - require.Equal(t, rawReference, raw) -} - -func TestInfoFieldToRaw(t *testing.T) { - val := newInfoField() - reference := &val - rawReference := newInfoFieldRaw() - require.Equal(t, rawReference, reference.ToRaw()) - reference = nil - require.Equal(t, ([]byte)(nil), reference.ToRaw()) -} - -func TestValidatePathEndProperties(t *testing.T) { - for i := 0; i < 4; i++ { - pep := PathEndProps(i) - err := pep.Validate() - require.NoError(t, err) - } - pep := PathEndProps(4) - err := pep.Validate() - require.Error(t, err) - - for i := 0; i < 4; i++ { - pep := PathEndProps(i << 4) - err := pep.Validate() - require.NoError(t, err) - } - pep = PathEndProps(4 << 4) - err = pep.Validate() - require.Error(t, err) - - pep = PathEndProps(0x10 | 0x04) - err = pep.Validate() - require.Error(t, err) -} - -func TestValidatePathEndPropsWithPathType(t *testing.T) { - cases := []struct { - PT PathType - EP PathEndProps - Valid bool - }{ - // core path - {CorePath, StartLocal | EndLocal, true}, - {CorePath, StartLocal | EndLocal | EndTransfer, true}, - {CorePath, StartTransfer | EndTransfer, true}, - {CorePath, StartLocal, true}, - {CorePath, StartTransfer, true}, - {CorePath, EndLocal, false}, - {CorePath, 0, false}, - // up path - {UpPath, StartLocal, true}, - {UpPath, StartLocal | EndLocal | EndTransfer, true}, - {UpPath, 0, false}, - {UpPath, StartTransfer, false}, - {UpPath, StartTransfer | StartLocal, false}, - // down path - {DownPath, EndLocal, true}, - {DownPath, EndLocal | StartLocal | StartTransfer, true}, - {DownPath, 0, false}, - {DownPath, EndTransfer, false}, - {DownPath, EndTransfer | EndLocal, false}, - // peering up path - {PeeringUpPath, StartLocal | EndLocal, true}, - {PeeringUpPath, StartLocal | EndLocal | EndTransfer, true}, - {PeeringUpPath, 0, false}, - {PeeringUpPath, StartLocal, false}, - {PeeringUpPath, StartLocal | StartTransfer | EndLocal, false}, - {PeeringUpPath, StartTransfer | EndLocal, false}, - {PeeringUpPath, EndLocal, false}, - // peering down path - {PeeringDownPath, EndLocal | StartLocal, true}, - {PeeringDownPath, EndLocal | StartLocal | StartTransfer, true}, - {PeeringDownPath, 0, false}, - {PeeringDownPath, EndLocal, false}, - {PeeringDownPath, EndLocal | EndTransfer | StartLocal, false}, - {PeeringDownPath, EndTransfer | StartLocal, false}, - {PeeringDownPath, StartLocal, false}, - } - for i, c := range cases { - name := fmt.Sprintf("iteration %d", i) - t.Run(name, func(t *testing.T) { - c := c - t.Parallel() - err := c.EP.ValidateWithPathType(c.PT) - if c.Valid { - require.NoError(t, err) - } else { - require.Error(t, err) - } - }) - } -} - -func TestAllocationBeadsMinMax(t *testing.T) { - cases := []struct { - Trail AllocationBeads - Min BWCls - }{ - {newAllocationBeads(), 0}, - {newAllocationBeads(0, 1), 1}, - {newAllocationBeads(0, 3, 0, 1), 1}, - {newAllocationBeads(0, 3, 0, 255), 3}, - } - for i, c := range cases { - name := fmt.Sprintf("iteration %d", i) - t.Run(name, func(t *testing.T) { - c := c - t.Parallel() - require.Equal(t, c.Min, c.Trail.MinMax()) - }) - } -} - -func TestValidateToken(t *testing.T) { - tok := newToken() - err := tok.Validate() - require.NoError(t, err) - tok.HopFields = []HopField{} - err = tok.Validate() - require.Error(t, err) -} - -func TestTokenLen(t *testing.T) { - tok := newToken() - require.Equal(t, len(newTokenRaw()), tok.Len()) -} - -func TestTokenFromRaw(t *testing.T) { - referenceRaw := newTokenRaw() - reference := newToken() - tok, err := TokenFromRaw(referenceRaw) - require.NoError(t, err) - require.Equal(t, reference, *tok) - - // buffer too small - _, err = TokenFromRaw(referenceRaw[:3]) - require.Error(t, err) - - // one hop field less - tok, err = TokenFromRaw(referenceRaw[:len(referenceRaw)-HopFieldLen]) - require.NoError(t, err) - require.Len(t, tok.HopFields, len(reference.HopFields)-1) -} -func TestTokenRead(t *testing.T) { - tok := newToken() - rawReference := newTokenRaw() - buf := make([]byte, len(rawReference)) - c, err := tok.Read(buf) - require.NoError(t, err) - require.Equal(t, len(buf), c) - require.Equal(t, rawReference, buf) - - // buffer too small - _, err = tok.Read(buf[:len(rawReference)-1]) - require.Error(t, err) -} - -func TestTokenToRaw(t *testing.T) { - tok := newToken() - raw := newTokenRaw() - require.Equal(t, raw, tok.ToRaw()) -} - -func newInfoField() InfoField { - return InfoField{ - ExpirationTick: 384555855, - BWCls: 13, - RLC: 4, - Idx: 2, - PathType: E2EPath, - } -} - -func newInfoFieldRaw() []byte { - return xtest.MustParseHexString("16ebdb4f0d042500") -} - -func newHopField(ingress, egress uint16, mac []byte) *HopField { - hf := HopField{ - Ingress: ingress, - Egress: egress, - } - if len(mac) < len(hf.Mac) { - panic(fmt.Errorf("mac is too short: %d", len(mac))) - } - copy(hf.Mac[:], mac) - return &hf -} - -func newToken() Token { - return Token{ - InfoField: newInfoField(), - HopFields: []HopField{ - *newHopField(1, 2, xtest.MustParseHexString("badcffee")), - *newHopField(1, 2, xtest.MustParseHexString("baadf00d")), - }, - } -} -func newTokenRaw() []byte { - return xtest.MustParseHexString("16ebdb4f0d04250000010002badcffee00010002baadf00d") -} - -func mustParseSegmentID(s string) SegmentID { - id, err := SegmentIDFromRaw(xtest.MustParseHexString(s)) - if err != nil { - panic(err) - } - return *id -} - -// newAllocationBeads (1,2,3,4) returns two beads {alloc: 1, max: 2}, {alloc:3, max:4} -func newAllocationBeads(beads ...BWCls) AllocationBeads { - if len(beads)%2 != 0 { - panic("must have an even number of parameters") - } - ret := make(AllocationBeads, len(beads)/2) - for i := 0; i < len(beads); i += 2 { - ret[i/2] = AllocationBead{AllocBW: beads[i], MaxBW: beads[i+1]} - } - return ret -} diff --git a/tools/topogen.py b/tools/topogen.py index c01a1cc7b..209dc75e0 100755 --- a/tools/topogen.py +++ b/tools/topogen.py @@ -47,8 +47,6 @@ def add_arguments(parser): parser.add_argument('--sig', action='store_true', help='Generate a SIG per AS (only available with -d, the SIG image needs\ to be built manually e.g. when running acceptance tests)') - parser.add_argument('-qos', '--colibri', action='store_true', - help='Generate COLIBRI service') parser.add_argument('--features', help='Feature flags to enable, a comma separated list\ e.g. foo,bar enables foo and bar feature.') return parser diff --git a/tools/topology/common.py b/tools/topology/common.py index b12326da0..934725eff 100644 --- a/tools/topology/common.py +++ b/tools/topology/common.py @@ -30,14 +30,12 @@ "control_service", "discovery_service", "border_routers", - "colibri_service", ) BR_CONFIG_NAME = 'br.toml' BS_CONFIG_NAME = 'bs.toml' CS_CONFIG_NAME = 'cs.toml' PS_CONFIG_NAME = 'ps.toml' -CO_CONFIG_NAME = 'co.toml' SD_CONFIG_NAME = 'sd.toml' DISP_CONFIG_NAME = 'disp.toml' SIG_CONFIG_NAME = 'sig.toml' diff --git a/tools/topology/config.py b/tools/topology/config.py index 948ed97f8..5fcabb91c 100644 --- a/tools/topology/config.py +++ b/tools/topology/config.py @@ -130,7 +130,6 @@ def _generate_go(self, topo_dicts): go_gen.generate_br() go_gen.generate_sciond() go_gen.generate_control_service() - go_gen.generate_co() go_gen.generate_disp() def _go_args(self, topo_dicts): diff --git a/tools/topology/go.py b/tools/topology/go.py index 85e4c6371..36c82537e 100644 --- a/tools/topology/go.py +++ b/tools/topology/go.py @@ -19,7 +19,6 @@ # Stdlib import os import toml -import yaml from typing import Mapping # SCION @@ -35,7 +34,6 @@ translate_features, SD_API_PORT, SD_CONFIG_NAME, - CO_CONFIG_NAME, ) from topology.net import socket_address_str, NetworkDescription, IPNetwork @@ -45,11 +43,8 @@ DEFAULT_BR_PROM_PORT, SCIOND_PROM_PORT, DISP_PROM_PORT, - CO_PROM_PORT, ) -DEFAULT_COLIBRI_TOTAL_BW = 1000 - class GoGenArgs(ArgsBase): def __init__(self, args, topo_config, topo_dicts, @@ -140,96 +135,6 @@ def _build_control_service_conf(self, topo_id, ia, base, name, infra_elem, ca): raw_entry['ca'] = {'mode': 'in-process'} return raw_entry - def generate_co(self): - if not self.args.colibri: - return - for topo_id, topo in self.args.topo_dicts.items(): - for elem_id, elem in topo.get("colibri_service", {}).items(): - # only a single Go-CO per AS is currently supported - if elem_id.endswith("-1"): - base = topo_id.base_dir(self.args.output_dir) - co_conf = self._build_co_conf(topo_id, topo["isd_as"], base, elem_id, elem) - write_file(os.path.join(base, elem_id, CO_CONFIG_NAME), toml.dumps(co_conf)) - traffic_matrix = self._build_co_traffic_matrix(topo_id) - write_file(os.path.join(base, elem_id, 'matrix.yml'), - yaml.dump(traffic_matrix, default_flow_style=False)) - rsvps = self._build_co_reservations(topo_id) - write_file(os.path.join(base, elem_id, 'reservations.yml'), - yaml.dump(rsvps, default_flow_style=False)) - - def _build_co_conf(self, topo_id, ia, base, name, infra_elem): - config_dir = '/share/conf' if self.args.docker else base - raw_entry = { - 'general': { - 'ID': name, - 'ConfigDir': config_dir, - 'ReconnectToDispatcher': True, - }, - 'log': self._log_entry(name), - 'trust_db': { - 'connection': os.path.join(self.db_dir, '%s.trust.db' % name), - }, - 'tracing': self._tracing_entry(), - 'metrics': self._metrics_entry(infra_elem, CO_PROM_PORT), - 'features': translate_features(self.args.features), - } - return raw_entry - - def _build_co_traffic_matrix(self, ia): - """ - Creates a NxN traffic matrix for colibri with N = len(interfaces) - """ - topo = self.args.topo_dicts[ia] - if_ids = {iface for br in topo['border_routers'].values() for iface in br['interfaces']} - if_ids.add(0) - bw = int(DEFAULT_COLIBRI_TOTAL_BW / (len(if_ids) - 1)) - traffic_matrix = {} - for inIfid in if_ids: - traffic_matrix[inIfid] = {} - for egIfid in if_ids.difference({inIfid}): - traffic_matrix[inIfid][egIfid] = bw - return traffic_matrix - - def _build_co_reservations(self, ia): - """ - Generates a dictionary of reservations with one entry per core AS (if "ia" is core) - excluding itself, or a pair (up and down) per core AS in the ISD if "ia" is not core. - """ - rsvps = {} - this_as = self.args.topo_dicts[ia] - if this_as['Core']: - for dst_ia, topo in self.args.topo_dicts.items(): - if dst_ia != ia and topo['Core']: - rsvps['Core-%s' % dst_ia] = self._build_co_reservation(dst_ia, 'Core') - else: - for dst_ia, topo in self.args.topo_dicts.items(): - if dst_ia != ia and dst_ia._isd == ia._isd and topo['Core']: - # reach this core AS in the same ISD - rsvps['Up-%s' % dst_ia] = self._build_co_reservation(dst_ia, 'Up') - rsvps['Down-%s' % dst_ia] = self._build_co_reservation(dst_ia, 'Down') - return rsvps - - def _build_co_reservation(self, dst_ia, path_type): - start_props = {'L', 'T'} - end_props = {'L', 'T'} - if path_type == 'Up': - start_props.remove('T') - elif path_type == 'Down': - end_props.remove('T') - return { - 'desired_size': 27, - 'ia': str(dst_ia), - 'max_size': 30, - 'min_size': 1, - 'path_predicate': '%s#0' % dst_ia, - 'path_type': path_type, - 'split_cls': 8, - 'end_props': { - 'start': list(start_props), - 'end': list(end_props) - } - } - def generate_sciond(self): for topo_id, topo in self.args.topo_dicts.items(): base = topo_id.base_dir(self.args.output_dir) diff --git a/tools/topology/prometheus.py b/tools/topology/prometheus.py index 94cc932ff..9a896a64f 100644 --- a/tools/topology/prometheus.py +++ b/tools/topology/prometheus.py @@ -41,7 +41,6 @@ CS_PROM_PORT = 30452 SCIOND_PROM_PORT = 30455 SIG_PROM_PORT = 30456 -CO_PROM_PORT = 30457 DISP_PROM_PORT = 30441 DEFAULT_BR_PROM_PORT = 30442 diff --git a/tools/topology/topo.py b/tools/topology/topo.py index 46f8c9a58..e92f8106c 100644 --- a/tools/topology/topo.py +++ b/tools/topology/topo.py @@ -52,7 +52,6 @@ DEFAULT_BEACON_SERVERS = 1 DEFAULT_CONTROL_SERVERS = 1 -DEFAULT_COLIBRI_SERVERS = 1 UNDERLAY_4 = 'UDP/IPv4' UNDERLAY_6 = 'UDP/IPv6' @@ -148,8 +147,6 @@ def _register_addrs(self, topo_id, as_conf): def _register_srv_entries(self, topo_id, as_conf): srvs = [("control_servers", DEFAULT_CONTROL_SERVERS, "cs")] - if self.args.colibri: - srvs.append(("colibri_servers", DEFAULT_COLIBRI_SERVERS, "co")) for conf_key, def_num, nick in srvs: self._register_srv_entry(topo_id, as_conf, conf_key, def_num, nick) @@ -257,8 +254,6 @@ def _generate_as_topo(self, topo_id, as_conf): def _gen_srv_entries(self, topo_id, as_conf): srvs = [("control_servers", DEFAULT_CONTROL_SERVERS, "cs", "control_service")] srvs.append(("control_servers", DEFAULT_CONTROL_SERVERS, "cs", "discovery_service")) - if self.args.colibri: - srvs.append(("colibri_servers", DEFAULT_COLIBRI_SERVERS, "co", "colibri_service")) for conf_key, def_num, nick, topo_key in srvs: self._gen_srv_entry(topo_id, as_conf, conf_key, def_num, nick, topo_key) @@ -281,8 +276,6 @@ def _gen_srv_entry(self, topo_id, as_conf, conf_key, def_num, nick, def _default_ctrl_port(self, nick): if nick == "cs": return 30252 - if nick == "co": - return 30257 print('Invalid nick: %s' % nick) sys.exit(1) From 2ce7932c0b0ae94679e3fdc08425332d49dbc904 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Mon, 31 Jul 2023 15:48:30 +0200 Subject: [PATCH 042/255] doc: update setup.rst (#4373) Update instructions to include Fedora as a supported platform and to link to the most relevant instructions on the docker site. Note: technically, support for Fedora, #4371, is still work in progress. --- doc/dev/setup.rst | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/doc/dev/setup.rst b/doc/dev/setup.rst index 6d6ec114a..e1a87a126 100644 --- a/doc/dev/setup.rst +++ b/doc/dev/setup.rst @@ -6,11 +6,19 @@ Setting up the Development Environment Prerequisites ------------- -#. Make sure that you are using a clean and recently updated **Ubuntu 18.04**. - Other Ubuntu versions (or systems) will usually be fine too, but some of the tooling may not work. +#. Make sure that you are using a clean and recently updated linux distribution. Distributions that are + known to work are: + + * **Ubuntu** release 18.04 or later. + * **Fedora** release 38 or later. + * **Amazon** Linux 2. + + Other Linux environments will usually be fine too, but some of the tooling might need + tweaking. If you make things work for other distributions, please update this list. + This environment assumes you're running as a non-root user with ``sudo`` access. #. Install ``docker``. - Please follow the instructions for `docker-ce `_. + Please follow the instructions for `docker server `_. Then, add your user to the ``docker`` group: ``sudo usermod -a -G docker ${LOGNAME}``, where ``${LOGNAME}`` is replaced with your user name. Log out and log back in so that your membership of the ``docker`` group is seen by the shell session. From df0d6673fe78592d6bdcbd5d5b5f311a72b11424 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 3 Aug 2023 17:27:13 +0200 Subject: [PATCH 043/255] doc: control service manual (#4361) Add a conceptual description of the control plane and a reference manual for the control service. The control plane description is mostly based on the IETF SCION control plane specification draft (https://www.ietf.org/archive/id/draft-dekater-scion-controlplane-00html). The reference manual for the control service describes the many command line flags, environment variables, configuration files and APIs. This documentation highlights a variety of usability shortcomings, redundancies and inconsistencies that should be addressed eventually. --- doc/beacon-metadata.rst | 60 +-- doc/conf.py | 1 + doc/control-plane.rst | 294 ++++++++++- doc/cryptography/ca-operations.rst | 2 + doc/cryptography/drkey.rst | 4 + doc/glossary.rst | 36 +- doc/manuals/common.rst | 10 +- doc/manuals/control.rst | 815 +++++++++++++++++++++++++++++ doc/manuals/control/http-api.rst | 6 + doc/manuals/router.rst | 9 + doc/manuals/router/http-api.rst | 3 + doc/overview.rst | 23 + doc/protocols/scion-header.rst | 3 + doc/requirements.in | 1 + doc/requirements.txt | 126 ++++- 15 files changed, 1323 insertions(+), 70 deletions(-) diff --git a/doc/beacon-metadata.rst b/doc/beacon-metadata.rst index deaa479ad..0086d95ef 100644 --- a/doc/beacon-metadata.rst +++ b/doc/beacon-metadata.rst @@ -294,64 +294,10 @@ are available: | Notes | The notes for each AS on the path | +-------------------+---------------------------------------------------------------------------------+ -Configuration File Format -========================= - -The control service obtains the information for the ``StaticInfoExtension`` -for the PCBs it sends out from a JSON configuration file, ``staticInfoConfig.json``. - -There is one top-level entry for each type of metadata. All entries are optional. - -- ``Latency`` is a map where the key is Interface ID ``i`` and the values are: - - +-------------+-------------------------------------------+-------------------------------------------------+ - | Name | Type | Description | - +=============+===========================================+=================================================+ - | ``Inter`` | Duration | Latency from interface ``i`` to remote AS | - +-------------+-------------------------------------------+-------------------------------------------------+ - | ``Intra`` | Map: Interface ID ``j`` : Duration | Latency from interface ``i`` to interface ``j`` | - +-------------+-------------------------------------------+-------------------------------------------------+ - -- ``Bandwidth`` is a map where the key is Interface ID ``i`` and the values are: - - +-------------+-------------------------------------------+-----------------------------------------------------------------+ - | Name | Type | Description | - +=============+===========================================+=================================================================+ - | ``Inter`` | Integer | Bandwidth in Kbit/s between interface ``i`` and the remote AS | - +-------------+-------------------------------------------+-----------------------------------------------------------------+ - | ``Intra`` | Map: Interface ID ``j`` : Integer | Bandwidth in Kbit/s between interface ``i`` and interface ``j`` | - +-------------+-------------------------------------------+-----------------------------------------------------------------+ - -- ``Geo`` is a map where the key is Interface ID ``i`` and the values are: - - +-----------------+-----------------+-----------------------------------------------+ - | Name | Type | Description | - +=================+=================+===============================================+ - | ``Latitude`` | Decimal value | Longitude GPS coordinates of interface ``i`` | - +-----------------+-----------------+-----------------------------------------------+ - | ``Longitude`` | Decimal value | Latitude GPS coordinate of interface ``i`` | - +-----------------+-----------------+-----------------------------------------------+ - | ``Address`` | String | Address of interface ``i`` | - +-----------------+-----------------+-----------------------------------------------+ - -- ``LinkType`` is a map where the key is Interface ID ``i`` and the value is one of - - - ``"direct"`` - - ``"multihop"`` - - ``"opennet"`` - -- ``Hops`` is a map where the key is Interface ID ``i`` and the values are: - - +-------------+------------------------------------+----------------------------------------------------------------------+ - | Name | Type | Description | - +=============+====================================+======================================================================+ - | ``Intra`` | Map: Interface ID ``j`` : Integer | Number of internal hops between interface ``i`` and interface ``j`` | - +-------------+------------------------------------+----------------------------------------------------------------------+ - -- ``Note`` is a string. +.. _path-metadata-example-conf: Example Configuration ---------------------- +===================== Let us look at an AS with three interfaces with IDs 1, 2, 3 and 5 which looks like the diagram below. The values attached to the connections @@ -360,7 +306,7 @@ represent the latency in milliseconds between interfaces. .. figure:: fig/beacon_metadata/example_config_metrics.png :width: 50% -The configuration file for this AS could then look like this: +The :ref:`staticInfoConfig.json ` configuration file for this AS could then look like this: .. code:: JSON diff --git a/doc/conf.py b/doc/conf.py index 4a466f4c7..a3bd61c41 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -21,6 +21,7 @@ 'recommonmark', 'sphinx_rtd_theme', 'sphinx.ext.extlinks', + 'sphinxcontrib.openapi', ] # Add any paths that contain templates here, relative to this directory. diff --git a/doc/control-plane.rst b/doc/control-plane.rst index 1ab5645bb..eca9ce072 100644 --- a/doc/control-plane.rst +++ b/doc/control-plane.rst @@ -10,11 +10,299 @@ Control Plane hidden-paths beacon-metadata + +Introduction +============ + The SCION control plane is responsible for discovering path segments and making them available to endpoints. This includes path-segment exploration (also called "beaconing"), registration, lookup, and finally the combination of path-segments to end-to-end paths. -.. admonition:: TODO +.. Note: content based on (extracts from) IETF draft draft-dekater-scion-controlplane-00. + +The **control service** is responsible for the path exploration and registration processes in the +control plane. +It is the main control-plane infrastructure component within each SCION :term:`AS`. +The control service of an AS has the following tasks: + +- Generating, receiving, and propagating :term:`Path Construction Beacons (PCBs) `. + Periodically, the control service of a core AS generates a set of PCBs, which are forwarded to the + child ASes or neighboring core ASes. + In the latter case, the PCBs are sent over policy-compliant paths to discover multiple paths + between any pair of core ASes. +- Selecting and registering the set of path segments via which the AS wants to be reached. +- Managing certificates and keys to secure inter-AS communication. + Each PCB contains signatures of all on-path ASes. + Every time the control service of an AS receives a PCB, it validates the PCB's authenticity. + When the control service lacks an intermediate certificate, it can query the control service of + the neighboring AS that sent the PCB. + +Path Segments +------------- + +As described previously, the main goal of SCION's control plane is to create and manage path +segments, which can then be combined into forwarding paths to transmit packets in the data plane. +SCION distinguishes the following types of path segments: + +- A path segment from a non-core AS to a core AS is an *up-segment*. +- A path segment from a core AS to a non-core AS is a *down-segment*. +- A path segment between core ASes is a *core-segment*. + +So each path segment either ends at a core AS, or starts at a core AS, or both. + +.. note:: + + There are no SCION path segments that start and end at a non-core AS. However, when combining + path segments into an end-to-end SCION path, shortcuts and peering-links can be used. + +All path segments are reversible: A core-segment can be used bidirectionally, and an up-segment can +be converted into a down-segment, or vice versa, depending on the direction of the end-to-end path. +This means that all path segments can be used to send data traffic in both directions. + +.. _control-plane-beaconing: + +Path Exploration (Beaconing) +============================ + +**Path exploration** is the process where an AS discovers paths to other ASes. In SCION, this +process is referred to as *beaconing*. + +In SCION, the *control service* of each AS is responsible for the beaconing process. +The control service generates, receives, and propagates *path-segment construction beacons (PCBs)* +on a regular basis, to iteratively construct path segments. +PCBs contain topology and authentication information, and can also include additional metadata that +helps with path management and selection. +The beaconing process itself is divided into routing processes on two levels, where *inter-ISD* or +core beaconing is based on the (selective) sending of PCBs without a defined direction, and +*intra-ISD* beaconing on top-to-bottom propagation. +This division of routing levels is a key architectural decision of SCION and important for achieving +a better scalability. + +- *Inter-ISD or core beaconing* is the process of constructing path segments between core ASes in + the same or in different ISDs. During core beaconing, the control service of a core AS either + initiates PCBs or propagates PCBs received from neighboring core ASes to other neighboring core + ASes. Core beaconing is periodic; PCBs are sent over policy-compliant paths to discover multiple + paths between any pair of core ASes. +- *Intra-ISD beaconing* creates path segments from core ASes to non-core ASes. For this, the control + service of a core AS creates PCBs and sends them to the non-core child ASes (typically customer + ASes). The control service of a non-core child AS receives these PCBs and forwards them to its + child ASes, and so on. This procedure continues until the PCB reaches an AS without any customer + (leaf AS). As a result, all ASes within an ISD receive path segments to reach the core ASes of + their ISD. + +On its way, a PCB accumulates cryptographically protected path- and forwarding information per +traversed AS. At every AS, metadata as well as information about the AS's ingress and egress +interfaces are added to the PCB. + +Origination of PCBs +------------------- + +Every core AS originates PCBs at regular intervals, and sends these to all egress interfaces to +connected neighbor ASes. +An originated PCB sent to a neighboring core ASes initiates an inter-ISD beacon, ultimately +resulting in a core-segment. +An originated PCB sent to a child AS initiates the intra-ISD beacon creating an up/down segment. + +Propagation of PCBs +------------------- + +PCBs are propgated at regular intervals at each AS. +When PCBs are received, they are not propagated immediately, but put into temporary storage +until the next propagation event. +The selection and propagation of PCBs differs between the inter-ISD and intra-ISD beacon schemes. + +Core ASes implement the inter-ISD / core beaconing scheme. +For every interface connecting to a neighboring core AS: + +1. Select the best :math:`N` PCBs for each origin core AS. + This can take into account both the available PCBs as well as local policies and information + about the link to the neighbor. +2. Extend the selected PCBs by adding an *AS entry* +3. Send the extended PCBs over the interface + +Non-core ASes implement the intra-ISD / non-core beaconing scheme. +For every interface connecting to a child AS: + +1. Select the best :math:`N` PCBs. + This can take into account both the available PCBs as well as local policies and information + about the link to the child AS. +2. Extend the selected PCBs by adding an *AS entry* +3. Send the extended PCBs over the interface + +AS Entries +---------- + +Every AS adds a signed *AS entry* to the PCBs it originates, propagates or :ref:`registers `. + +This AS entry includes the relevant network topology information for this AS-hop +defined by the ingress and egress :term:`interface IDs ` of the beacon. +The so-called *hop field* includes a MAC that authorizes the use of this hop in the path +segment defined by the PCB, until it expires. +See the description of the :ref:`SCION Path ` in the data plane section for more +details on the hop field format and the MAC chaining mechanism. + +Additionally, an AS entry can contain :doc:`metadata ` such as the link MTU, +geographic locations of the AS routers, latencies, etc. + +For illustration, the following code blocks show the definition of the protobuf message definitions +for the AS entry "body" and the contained hop field information. +This is just a small excerpt of the relevant definitions. +See the `SCION Control Plane IETF draft (section "Components of a PCB") `_ +for a more complete discussion of the message formats and signature inputs, +or :file-ref:`proto/control_plane/v1/seg.proto` for the raw protocol definitions used in this project. + +.. literalinclude:: /../proto/control_plane/v1/seg.proto + :caption: AS entry protobuf message definition. + This data will be signed by the creating AS. + A PCB is essentially a sequence of such signed AS entries. + :language: proto + :start-at: message ASEntrySignedBody { + :end-at: } + +.. literalinclude:: /../proto/control_plane/v1/seg.proto + :caption: Hop field protobuf message definition. This is a part of the ``HopEntry``, refererred to + in the ``ASEntrySignedBody`` definition above. + :language: proto + :start-at: message HopField { + :end-at: } + +Peering Links +------------- + +PCBs do not traverse peering links. +Instead, available peering links are announced along with a regular path in the individual AS +entries of PCBs. +If both ASes at either end of a peering link have registered path segments that include a specific +peering link, then it can be used to during segment combination to create an end-to-end path. + +.. _control-plane-registration: + +Registration of Path Segments +============================= + +**Path registration** is the process where an AS transforms selected PCBs into path segments, +"terminating" them by adding a final AS entry with a zero egress interface, +and adds these segments to the relevant path databases, thus making them available for the path +lookup process. + +As mentioned previously, a non-core AS typically receives several PCBs representing path segments to +the core ASes of the ISD the AS belongs to. +Out of these PCBs, the non-core AS selects those down-path segments through which it wants to be +reached, based on AS-specific selection critera. +The next step is to register the selected down-segments with the control service of the +core AS that originated the PCB. + +Intra-ISD Path-Segment Registration +----------------------------------- + +Every *registration period* (determined by each AS), the AS's control service selects of +PCBs to transform into path segments: + +- Up-segments, which allow the infrastructure entities and endpoints in this AS to communicate with + core ASes. + Up-segments are registered in the local path database of the AS. +- Down-segments, which allow remote entities to reach this AS. + Down-segments are registered, via a remote-procedure call, in the path-segment database of the + core AS that originated the PCB. + As a result, a core AS's path database contains all down-segments registered by their + direct or indirect customer ASes. + +Core Path-Segment Registration +------------------------------ + +The core beaconing process creates PCBs from core AS to core AS. +Every *registration period*, the AS's control service selects sets of PCBs to turn into path +segments and register. +These selected core-segments are added to the local path database of the core AS that created the +segment (i.e. the one at the end of the beacon chain), so that local and remote endpoints can obtain +and use these core-segments. +In contrast to the down-segment registration procedure, there is no need to register core-segments +with other core ASes (as each core AS will receive PCBs originated from every other core AS). + +Path Lookup +=========== + +An endpoint (source) that wants to start communication with another endpoint (destination), needs +up to three path segments: + +- An up-path segment to reach the core of the source ISD +- a core-path segment to reach + + - another core AS in the source ISD, in case the destination AS is in the same source ISD, or + - a core AS in a remote ISD, if the destination AS is in another ISD, and + +- a down-path segment to reach the destination AS. + +The process to look up and fetch path segments consists of the following steps: + +1. First, the source endpoint queries the control service in its own AS (i.e., the source AS) for + the required segments. + The control service has up-path segments stored in its path database. +2. The control service in the source AS queries the control services of the reachable core ASes in + the source ISD, for core-path segments to core ASes in the destination ISD (which is either the + local or a remote ISD). + To reach the core control services, the control service of the source AS uses the locally stored + up-path segments. +3. The control service then queries the control services of the remote core ASes in the destination + ISD, to fetch down-path segments to the destination AS. + To reach the remote core ASes, the control service of the source AS uses the previously obtained + and combined up- and core segments. +4. Finally, the control service of the source AS returns all retrieved path segments to the source + endpoint. +5. The endpoint combines all path segments into an end-to-end path + +All remote path-segment lookups by the control service are cached. + +On SCION end hosts, a :doc:`SCION daemon ` is usually employed to do the +path-lookup on behalf of applications. This SCION daemon also caches path-segment lookup results. + +.. table:: Control services responsible for different types of path segments + + ============ =========================== + Segment Type Responsible control service(s) + ============ =========================== + Up-segment Control service of the source AS + Core-segment Control service of core ASes in source ISD + Down-segment Control service of core ASes in destination ISD (either the local ISD or a remote ISD) + ============ =========================== + +Path-Segment Combination +======================== + +The last step of the path-resolution process is to combine the available up-, core- and down- +path segments to end-to-end forwarding paths. +This path-segment combination process is done by each endpoint separately. +Typically, end hosts run the :doc:`SCION daemon ` which centralizes the +path-resolution process and returns fully formed end-to-end paths to applications. +However, applications could also choose to bypass the daemon and perform the path-resolution +directly. + +The figures below illustrate the various ways in which segments can be combined +to form end-to-end paths. +See the description of the :ref:`SCION Path` for the specifics on how these +end-to-end paths are encoded in the packet header. + +.. figure:: fig/beacon_metadata/path_combinations.png + :alt: Path Combinations + + Combination of path segments to paths: the blue circles represent the end + hosts; the shaded gray circles represent core ASes, possibly in different + ISDs; blue lines without arrow heads denote hops of created forwarding + paths; the dashed blue line denotes a peering link (labeled "p"); orange + lines with arrows stand for PCBs and indicate their dissemination direction; + dashed orange lines represent core beacons exchanged over core links + (labeled "c"). All created forwarding paths in cases 1a-1e traverse the ISD + core(s), whereas the paths in cases 2-4 do not enter the ISD core. + + +.. seealso:: + + :doc:`overview` + Introduction to the SCION architecture and core concepts. + + :doc:`data-plane` + Description of SCION packet header formats and processing rules for packet forwarding based + the packed-carried forwarding state. - Control plane overview and detailed description of beaconing, registration, lookup, and - combination + `IETF Draft SCION Control Plane `_ + Formal description and specification of the SCION control plane. diff --git a/doc/cryptography/ca-operations.rst b/doc/cryptography/ca-operations.rst index 3a582e5f9..379b6a373 100644 --- a/doc/cryptography/ca-operations.rst +++ b/doc/cryptography/ca-operations.rst @@ -120,6 +120,8 @@ To comply with custom security policies that dictate that a Root Key should sit behind an air gap, multiple CA certificates can be pre-generated for the same entity. +.. _ca-ops-as-certs: + AS Certificates =============== diff --git a/doc/cryptography/drkey.rst b/doc/cryptography/drkey.rst index a0e80d401..36c63c486 100644 --- a/doc/cryptography/drkey.rst +++ b/doc/cryptography/drkey.rst @@ -65,12 +65,16 @@ the :ref:`drkey-generic-derivation`. Both of them leverage the 4-level derivatio 4-level derivation ------------------ +.. _drkey-secret: + **Secret value (Level 0)** Each AS locally derives one :math:`SV_A^{protocol}` per protocol and epoch. This secret value is renewed at every epoch and it is only shared with trustworthy entities that require to derive keys on the fly for the specified protocol. +.. _drkey-as-as: + **AS-AS (Level 1)** The ``AS-AS`` key is derived locally in the AS :math:`A` CS (:math:`CS_A`) and exchanged diff --git a/doc/glossary.rst b/doc/glossary.rst index 561b6cbf9..0083dcdbc 100644 --- a/doc/glossary.rst +++ b/doc/glossary.rst @@ -27,6 +27,13 @@ Glossary In SCION, BFD is used to determine the liveness of the link between two border routers and trigger :term:`SCMP` error messages. + CA + Certificate Authority + + An entity that signs and issues digital certificates, certifying the ownership of a public + key by the named subject of the certificate. + CAs are a part of a public key infrastructure, like the SCION :term:`Control-Plane PKI`. + CP-PKI Control-Plane PKI @@ -34,6 +41,8 @@ Glossary allows to tie cryptographic keys to SCION AS identifiers. This is the machinery that allows to authenticate SCION control-plane messages. + See :doc:`/cryptography/index`. + End Host Endpoint A SCION **end host** is a computer or other device connected to a computer network in a @@ -48,13 +57,19 @@ Glossary End host is preferred where the focus is (physical or virtual) machines and the software running on them, and endpoint is used otherwise. + Interface ID + An interface ID is the AS-local identifier for an inter-domain link. + + The interface ID is an arbitrary 16-bit number between 1 and 65535, + assigned without external coordination by the operator of the AS. + ISD Isolation Domain An Isolation Domain (ISD) is a set of participating :term:`ASes `. ISDs can overlap, i.e. ASes can participate in multiple ISDs. - An ISD represents a scope for Certificate Authorities (CAs) in the :term:`Control-Plane PKI`; + An ISD represents a scope for :term:`CAs ` in the :term:`Control-Plane PKI`; CAs can issue certificates exclusively to ASes in their ISD. At the same time Isolation Domains also serve as a local routing domain. @@ -63,6 +78,17 @@ Glossary Only the core ASes (i.e. the ASes at the top(s) of this directed acyclic graph) need to participate in the less efficient inter-ISD path discovery. + See :ref:`overview-isds`. + + Beacon + PCB + Path-Segment Construction Beacon + + Path-Segment Construction Beacons are control-plane messages that are propagated through a + SCION network during the :ref:`path exploration ("beaconing") ` process. + On their way, PCBs accumulate authenticated network topology information (on the granularity + of :term:`ASes `). + SCMP SCION Control Message Protocol @@ -72,3 +98,11 @@ Glossary send error messages and for diagnostics (ping and traceroute). See :doc:`/protocols/scmp` for more information. + + TRC + Trust-Root Configuration + + Each :term:`ISD` has a separate trust-root configuration, specifying the core ASes acting as + :term:`CAs `. + + See :doc:`/cryptography/trc`. diff --git a/doc/manuals/common.rst b/doc/manuals/common.rst index 859ea7e56..6bc3e4b21 100644 --- a/doc/manuals/common.rst +++ b/doc/manuals/common.rst @@ -168,7 +168,7 @@ of the individual fields below. .. option:: attributes = [<"core">?], default [] - Role of this AS. ``["core"]`` for core-ASes, ``[]`` for non-core ASes. + Role of this AS. ``["core"]`` for core ASes, ``[]`` for non-core ASes. .. Note:: @@ -196,12 +196,9 @@ of the individual fields below. .. object:: interfaces - .. object:: + .. option:: - An interface ID is the AS-local identifier for an inter-domain link. - - The interface ID is an arbitrary number between 1 and 65535, - assigned without external coordination by the operator of the AS. + The :term:`interface ID ` for an inter-domain link. In this ``topology.json`` file, the ID is contained in a string. @@ -304,6 +301,7 @@ of the individual fields below. .. option:: Identifier for a control service instance. + Matches the :option:`general.id ` of a control service instance. .. option:: addr = , required diff --git a/doc/manuals/control.rst b/doc/manuals/control.rst index b7c26e729..0bcbe8017 100644 --- a/doc/manuals/control.rst +++ b/doc/manuals/control.rst @@ -2,6 +2,802 @@ Control Service *************** +:program:`control` is the SCION control service. +It discovers SCION paths by participating in the inter-domain path-dissemination process called +"beaconing". +It signs and validates the path information based on the :term:`Control-Plane PKI `. + +The :program:`control` service is also the recursive resolver for path information for endpoints in +the local AS. + +In ASes with the :ref:`CA role`, the :program:`control` service also acts as the +certificate authority from which ASes in the local ISD request renewed certificates (or as a proxy +thereof). + +See :doc:`/control-plane` for an introduction to the SCION control plane and the tasks of the +:program:`control` service. + +Command line reference +====================== + +.. program:: control + +Synopsis +-------- + +:program:`control` [:option:`--config \ ` | :option:`help ` | :option:`version `] + + +Options +------- + +.. option:: --config + + Specifes the :ref:`configuration file ` and starts the control service. + +.. option:: help, -h, --help [subcommand] + + Display help text for subcommand. + +.. option:: version + + Display version information. + +.. option:: sample [file] + + Display sample files. + + .. option:: config + + Display a sample :ref:`configuration file `. + + .. option:: policy + + Display a sample :ref:`beaconing policy file ` + +.. option:: completion [shell] + + Generate the autocompletion script for :program:`control` for the specified shell. + + Run :option:`control help completion ` for a list of the available shells. + + Run :option:`control help completion [shell] ` for usage information on the + autocomplete script for a particular shell. + + +Environment variables +--------------------- + +.. envvar:: SCION_TESTING_DRKEY_EPOCH_DURATION + + For **testing only**. + + Override the global duration for :doc:`/cryptography/drkey` epochs. + This can only work correctly if the same value is set for all connected control services in the + test network. + + The format is a :ref:`duration ` with unit suffix (e.g. ``10s``). + +Configuration +============= + +The :program:`control` service is configured with multiple files: + +- the :ref:`.toml ` file, + specified on the command line by the :option:`--config ` option, is the main + configuration file. + It configures common features like logging and metrics and + specifies the **configuration directory** from which all other configuration files are read. +- :ref:`topology.json `, contains information about the inter-AS links +- :ref:`beaconing policy ` configuration files +- :ref:`crypto/ and certs/ ` contain :term:`CP-PKI` certificates and private keys +- :ref:`keys/ ` contains the AS's forwarding secret keys +- :ref:`staticInfoConfig.json `, if it exists, specifies values for the :doc:`/beacon-metadata`. + +.. _control-conf-toml: + +Control service configuration +----------------------------- + +In addition to the :ref:`common .toml configuration options `, the control service +considers the following options. + +.. program:: control-conf-toml + +.. object:: general + + .. option:: general.id = (Required) + + An identifier for this control service. + + This is used to identify which parts of the :ref:`control-conf-topo` file are refering to self. + Thus, ``id`` must match a key in the :ref:`control-conf-topo` files' ``control_service`` section. + + .. option:: general.config_dir = (Required) + + Path to a directory containing the remaining configuration files. + + If this is a relative path, it is interpreted as relative to the current working directory of the + program (i.e. **not** relative to the location of this .toml configuration file). + + .. option:: general.reconnect_to_dispatcher = (Default: false) + + Transparently reconnect to the dispatcher on dispatcher failure or restarts. + + .. Warning:: + This should be set to ``true``, unless your service orchestration ensures that + failures of the dispatcher also trigger a restart of :program:`control`. + +.. object:: features + + Features is a container for generic, boolean feature flags (usually for experimental or + transitional features). + + .. option:: features.appropriate_digest_algorithm = (Default: false) + + Enables the CA module to sign issued certificates + with the appropriate digest algorithm instead of always using ECDSAWithSHA512. + + **Transition**: This behaviour should be enabled unless there is a specific requirement to + interface with older versions of SCION that don't support these certificates. + The default for this flag will be changed to ``true`` in future releases, and the flag will + eventually be removed. + +.. object:: api + + .. option:: api.addr = (Optional) + + Address at which to expose the :ref:`control-rest-api`, + in the form ``host:port``, ``ip:port`` or ``:port``. + +.. object:: tracing + + Tracing with `OpenTracing `_ / `Jaeger `_. + This is especially helpful when collecting the traces of multiple service instances, e.g. when + :doc:`running a local SCION topology `. + + .. option:: tracing.enabled = (Default = false) + + .. option:: tracing.debug = (Default = false) + + .. option:: tracing.agent = (Default = "localhost:6831") + + Address of the local agent that handles the reported traces. + +.. object:: quic + + .. option:: quic.address = (Optional) + + Local SCION address for inter-AS communication by QUIC/gRPC. + By default, the address used is that specified for this control service in its ``control_service`` entry of + the :ref:`control-conf-topo`. + +.. object:: beaconing + + .. option:: beaconing.origination_interval = (Default = "5s") + + Specifies the interval between originating beacons in a core AS. + + .. option:: beaconing.propagation_interval = (Default = "5s") + + Specifies the interval between propagating beacons. + + .. option:: beaconing.registration_interval = (Default = "5s") + + Specifies the interval between registering path segments. + + .. option:: beaconing.policies + + File paths for :ref:`control-conf-beacon-policies`. + If these are the empty string, the default policy is used. + + The different policies *may* point to the same file(s). + + .. option:: beaconing.policies.propagation = + .. option:: beaconing.policies.core_registration = + .. option:: beaconing.policies.up_registration = + .. option:: beaconing.policies.down_registration = + + + .. option:: beaconing.epic = (Default: false) + + Specifies whether the EPIC authenticators should be added to the beacons. + +.. object:: path + + .. option:: path.query_interval = (Default = "5m") + + Specifies after how much time path segments for a destination AS should be refetched. + + .. option:: path.hidden_paths_cfg = (Optional) + + Location of the :doc:`hidden paths ` configuration. + + The location is specified as a file path (relative to the working directory of the program) + or an HTTP/HTTPS URL. + +.. object:: ca + + .. option:: ca.mode = "disabled"|"in-process"|"delegating" (Default: "disabled") + + Mode defines whether the :program:`control` should handle certificate issuance requests. + This should be enabled in core ASes that are labeled as ``issuing`` ASes in the :term:`TRC`. + + If set to ``in-process``, :program:`control` handles certificate issuance requests on its own. + If set to ``delegating``, the certificate issuance is delegated to the service defined in + :option:`ca.service `. + + .. option:: ca.max_as_validity = (Default: "3d") + + Defines the the maximum lifetime for renewed AS certificates. + + .. option:: ca.service + + Configuration for the :term:`CA` service, + effective with the :option:`ca.mode ` mode ``delegating``. + + The CA service is expected to implement the API described by :file-ref:`spec/ca.gen.yml`. + + .. Hint:: + The `scionproto/scion `_ project does not include such + a standalone CA service implementation. + + The available options are: + + - use the built-in CA implementation (using :option:`ca.mode = "in-process" `), + - use the `netsys-lab/scion-ca `_ SCION CA + based on `smallstep's step-ca `_, + - ask SCION vendors for proprietary CA implementations and offerings, + - plug in your own CA service implementing the :file-ref:`spec/ca.gen.yaml` API. + + .. option:: ca.service.address = + + Address of the CA Service that handles the delegated certificate renewal requests. + Specified with scheme, for example ``https://ca-service.local``, and optional + path relative to the server, such as ``https://ca-service.local/dev-test``. + + .. option:: ca.service.shared_secret = + + Path to the PEM-encoded shared secret that is used to create JWT tokens. + + The shared secret file is re-read from disk at 5 second intervals. + + .. option:: ca.service.lifetime = (Default: "10m") + + Validity period (a :ref:`duration `) of JWT authorization tokens + for the CA service. + + .. option:: ca.service.client_id = (Default: general.id) + + Client identifier for the CA service. + Defaults to :option:`general.id `. + +.. option:: beacon_db (Required) + + :ref:`Database connection configuration ` + for received :term:`PCB`\s. + + This database holds beacons that may be candidates for propagation. + If it is destroyed, the control service may temporarily not have beacons to propagate to + downstream neighbor ASes, until fresh PCBs are received from upstream neighbor ASes. + +.. option:: trust_db (Required) + + :ref:`Database connection configuration ` + for :term:`Control-Plane PKI` information. + + This database file contains cached TRC and AS certificate chains. + If it is destroyed, the control service will load locally available TRCs and certificate chains + from the corresponding :ref:`configuration directory `, and fetch other + certificate information from authoritative ASes on-demand. + +.. option:: path_db (Required) + + :ref:`Database connection configuration ` + for Path Segment data. + + This database contains path segments, both explicitly registered segments resulting from the + beaconing process, as well as cached results from path segment queries. + If it is destroyed, the explicitly registered paths may be lost until + they are rediscovered by the beaconing process. The path segments from cached path segment + queries will be re-fetched on-demand. + +.. object:: trustengine.cache + + Control the **experimental** in-memory caching of ISD/AS attribute information extracted from + :term:`TRCs `. + + .. option:: trustengine.cache.disable = (Default: false) + + Disable caching entirely. + + .. option:: trustengine.cache.expiration = (Default: 60000000000) + + Expiration of cached entries in nanoseconds. + + **TODO:** this should be changed to accept values in :ref:`duration format `. + +.. object:: drkey + + Configuration for the optional and still somewhat **experimental** :doc:`Dynamically Recreatable Key (DRKey) infrastructure
`. + + See also :envvar:`SCION_TESTING_DRKEY_EPOCH_DURATION`. + + .. option:: drkey.level1_db (Optional) + + Enables the DRKey infrastructure if set. + + :ref:`Database connection configuration ` + for cached :ref:`AS-AS (Level 1) keys `. + + If it is destroyed, the control service may need to re-fetch keys from remote ASes. + + .. option:: drkey.secret_value_db + + Required if :option:`drkey.level1_db ` is set. + + :ref:`Database connection configuration ` + for key epochs and the corresponding :ref:`secret values (Level 0 keys) ` + derived from the :ref:`AS master keys `. + + .. warning:: + + This database is not a cache. + + If it is destroyed, the control service loses track of previously created key epochs. + As key derivation depends on the epoch, keys that have previously been requested / derived, + will not match any newly created keys. + The DRKey system is broken for this AS, at least until all entities have fetched new keys, + which may only happen after multiple epochs. + + .. option:: drkey.delegation = (Optional) + + Defines hosts with privileged access to obtain the protocol and epoch specific + :ref:`secret value (Level 0 key) `. + These hosts can locally derive keys shared with any remote AS, without having to request + them individually from the control service. + However, the hosts must be trusted to not abuse this, as they can also create keys + to impersonate any other host in the AS. + + The set of hosts authorized to access the secret value for delegated key derivation + are specified as a list of IP addresses per supported :ref:`DRKey protocol identifier `. + + .. code-block:: toml + + # Example + + [drkey.delegation] + scmp: ["203.0.113.17", "198.51.100.249"] + + .. option:: drkey.prefetch_entries = (Default: 10000) + + Maximum number of Level 1 keys that will be re-fetched preemptively before their expiration. + +.. _control-conf-topo: + +topology.json +------------- + +The :program:`control` service reads the ``control_service`` section of the :ref:`topology.json ` file. + +The entry referring to its own :option:`general.id ` +define the addresses that :program:`control` will listen on. + +The interface definitions in the ``border_router`` entries define the inter-AS links. +These entries define the beacons that :program:`control` will originate and propagate. + +.. _control-conf-beacon-policies: + +Beaconing policies +------------------ + +A beaconing policy is a YAML file, defining processing rules for path-segment construction and +registration. +There are four policies with different but related purposes, that can individually be configured +with the :option:`beacon.policies ` options: + +Propagation + Propagation is the process of receiving a beacon from a neighbor AS, extending it + with one's own AS entry and forwarding it to downstream neighbor ASes. + See :ref:`control-plane-beaconing`. + + The propagation policy determines which beacons are selected to be propagated and how they are + extended. + + Note that there is no separate policy type for beacon origination. The only policy value + affecting origination is the :option:`MaxExpTime `, which is + read from the propagation policy. + +Registration + Registration is the process of making beacons available as path-segments to the path lookup + process. + Beacons received from a neighbor AS are "terminated" by appending the own AS entry and registered + in a path-segment database, from which it can be later found with path-segment queries. + See :ref:`control-plane-registration`. + + CoreRegistration + Applies to the registration of core-segments in the local path store of a core AS. + + UpRegistration + Applies to the registration of up-segments in the local path store of a non-core AS. + + DownRegistration + Applies to the registration of down-segments. The policy is used by a non-core AS + to determine which down-segments it wants to make available to other ASes. + Each selected down-segments is registered, via a segment registration request, in the core AS + that originated it. + + .. note:: + There is currently no corresponding policy that applies to the processing of segment + registration requests in the core AS. + +From the description above, it is already evident that not all four policies are applicable for +core and non-core ASes. Summarizing this: + +.. table:: + + ================= ================================================ + AS type Applicable policies + ================= ================================================ + core Propagation, CoreRegistration + non-core Propagation, UpRegistration, DownRegistration + ================= ================================================ + + +The beaconing policy YAML configuration considers the following options: + +.. program:: control-conf-beacon-policy + +.. option:: Type = "Propagation"|"UpSegmentRegistration"|"DownSegmentRegistration"|"CoreSegmentRegistration" (Default: "") + + Restrict this policy configuration file to be used exclusively as one of the + :option:`beacon.policies ` options. + + Only as sanity check and organization of configuration files. No operational effect. + +.. option:: BestSetSize = int (Default: 20) + + Maximum number of segments to propagate/register **per origin AS**. + + In the ``Propagation`` policy, this parameter determines the number of beacons + propagated to neighbor ASes per origin AS. + That is, for each originating AS, up to ``BestSetSize`` beacons are forwarded. + For the core-beaconing process, the set of originating ASes are all other core ASes, which can + be very numerous. + + .. warning:: + + Keep this parameter reasonably low to avoid an explosion of beacon numbers. + +.. option:: CandidateSetSize = int (Default: 100) + + Maximum number of segments to keep in beacon store and consider for selection to best set **per + origin AS**. + +.. option:: MaxExpTime = uint8 (Default: 63) + + Defines the maximum relative expiration time for the AS Entry when originating, propagating or + terminating a PCB. + + .. note:: + For beacon origination, the ``MaxExpTime`` value from the ``Propagation`` policy is used. + + The 8 bit unsigned integer :ref:`ExpTime ` fields represents an expiration + relative to the origination timestamp of the segment, with a nonzero minimum and a maximum + of 24 hours: + + .. math:: + (1 + ExpTime) \cdot \frac{24\cdot60\cdot60}{256}\mathrm{s} + + Every increment of `ExpTime` represents 5 minute and 37.5 seconds in duration. + + ============= ================ + ``ExpTime`` Duration (h:m:s) + ============= ================ + 0 0:05:37.5 + 1 0:11:15 + 2 0:16:52.5 + ... ... + 9 0:56:15 + 10 1:01:52.5 + 11 1:07:30 + ... ... + 63 6:00:00 + ... ... + 254 23:54:22.5 + 255 24:00:00 + ============= ================ + +.. option:: Filter + + Filters restrict the allowed beacons for the purposes of the policy (i.e. for propagation or + the different forms of registration). + + Filters are applied when a beacon is received, resulting in a "usage" classification of the + beacon that is stored in the local beacon database. + Therefore, when the policy is changed, it will only be effective for newly received beacons. + + .. note:: + + Filters are currently not very expressive. Specifically, they cannot express filtering rules + that take into account the ingress or egress interface of the beacon. + + There are plans to extend this functionality but so far there are no concrete proposals. + If you're interested in working on this, get in contact in the :ref:`chat ` or create a + :ref:`proposal ` on github. + + .. option:: MaxHopsLength = + + Upper bound for the allowed number of AS entries in a received PCB. + + Filters are applied for received PCBs, before extending the segment. + Consequently, a propagated/terminated PCB may have up to ``MaxHopsLength + 1`` AS entries. + + .. option:: AsBlackList = + + Deny-list for ASes. + PCBs with any AS entry from any of the specified AS identifiers will be rejected. + + .. option:: IsdBlackList = + + Deny-list for ISDs. + PCBs with any AS entry from any of the specified ISD identifiers will be rejected. + + .. option:: AllowIsdLoop = (Default: true) + + Specifies whether ISD loops are allowed. + + A PCB is considered to be an ISD loop if it leaves and then re-enters an ISD. + +.. _control-conf-cppki: + +Control-Plane PKI +----------------- + +TRCs + :option:`/certs ` + + The :term:`TRC`\s for the :term:`Control-Plane PKI` are loaded from here. + TRCs are also written back to the :option:`trust_db `. + + Any TRC loaded from this directory will be written back to the trust_db. + Updated TRCs fetched from authoritative core ASes are stored both here in the filesystem and + in the trust_db. + + :program:`control` scans this directory for new TRCs at startup, and also when requesting signing + keys and the corresponding certificate chains. + + .. note:: + :program:`control` does **not** create TRCs. + TRC creation is an offline process, the :doc:`/cryptography/trc-signing-ceremony`. + + However, the :program:`control` does fetch new TRCs from neighbor ASes and store them into + this directory (/certs). + + +AS Certificates and Keys + :option:`/crypto/as ` + + :ref:`AS certificate chains ` and the corresponding keys, + used for signing control-plane messages and authenticating TLS sessions to other control + services, are loaded from here. + Certificates are also written back to the :option:`trust_db ` (but + keys are not). + + :program:`control` scans this directory for new certificates at startup, and also when loading + keys on demand. + + Keys are loaded from this directory on demand, with an in-memory cache with a lifetime of 5 + seconds. + + .. note:: + :program:`control` does **not** request renewal of its AS certificates. + + Certificate renewal can be requested using the :ref:`scion-pki_certificate_renew` tool. + Because AS certificates have short lifetimes, this *should* be automated by the operator. + +CA Certificates and Keys + :option:`/crypto/ca ` + + If the in-process :term:`CA` is used, :option:`ca.mode = "in-process" `, + the :ref:`CA certificates ` and corresponding keys are read from this + directory on demand, whenever a certificate renewal request is handled. + + .. note:: + Even if it is operating with active CA mode, + :program:`control` does **not** issue initial certificates for new ASes. + Issuance of initial AS certificates is an offline process. See :ref:`ca-ops-as-certs`. + +The control service is not directly involved in the creation of TRCs and consequently it is not +concerned with voting certificates. + +.. _control-conf-keys: + +Keys +---- + +:program:`control` loads the forwarding secret keys ``master0.key``/``master1.key`` from :option:`/keys `. + +The key files contain a base64-encoded high-entropy random string. +The keys should be exactly 16 bytes long (corresponding to a base64 encoding of 24 bytes with two trailing pad bytes ``==``). +These keys must be identical to the :ref:`corresponding keys used by the routers `. + +.. note:: + The :program:`router` and :doc:`control` currently use these keys as input for PBKDF2 to generate + the actual forwarding key. Consequently, keys of any size can currently be used. This may be changed + to only accept high-entropy 16 byte keys directly in the future. + +.. _control-conf-path-metadata: + +Path Metadata +------------- + +The ``StaticInfoExtension`` PCB extension allows to announce :doc:`path metadata in beacons `. + +:program:`control` loads the information for the ``StaticInfoExtension`` +for its AS entries from the optional JSON configuration file +:option:`/staticInfoConfig.json ` if it exists. + +This configuration is **optional**. +If the file does not exist, or if the configuration does not specify values for certain metadata +types or for certain interfaces, the corresponding ``StaticInfoExtension`` will either be omitted or +include only partial metadata. + +If the configuration file exists, it must be syntactically valid. + +The structure of the configuration is presented as pseudo-JSON with a more detailed explanation +of the individual fields below. + +.. code-block:: yaml + :caption: Pseudo-JSON description of the structure of the ``staticInfoConfig.json`` configuration file. + :name: staticinfoconfig-json-structure + + { + "Latency": { + : { + "Inter": , + "Intra": { + : + # ... + } + } + # ... + }, + "Bandwidth": { + : { + "Inter": , + "Intra": { + : + # ... + } + } + # ... + }, + "Geo": { + : { + "Latitude": , + "Longitude": , + "Address": + } + # ... + }, + "Linktype": { + : <"direct"|"multihop"|"opennet"> + # ... + }, + "Hops": { + : { + "Intra": { + : + # ... + } + } + # ... + }, + "Note": + } + +.. seealso:: + + :ref:`Example staticInfoConfig.json ` in the + :doc:`/beacon-metadata` section. + + +There is one top-level entry for each type of metadata, all of which are optional. +:term:`Interface ID` keys must be specified as strings (not numbers), e.g. ``"5"``. + +.. program:: control-conf-metadata + +.. option:: Latency + + Object where the keys are Interface ID ``i`` and the values are objects with: + + .. option:: Inter = + + Latency from interface ``i`` to the associated remote AS border router. + + .. option:: Intra = + + Latency from interface ``i`` to interface ``j``. + +.. option:: Bandwidth + + Object where the keys are Interface ID ``i`` and the values are objects with: + + .. option:: Inter = + + Bandwidth in Kbit/s between interface ``i`` and the associated remote AS border router. + + .. option:: Intra = + + Bandwidth in Kbit/s between interface ``i`` to interface ``j``. + +.. option:: Geo + + Object where the keys are Interface ID ``i`` and the values are objects with: + + .. option:: Latitude = + + Latitude GPS coordinate of interface ``i``. + + .. option:: address = + + Free-form civic address of interface ``i``. + +.. option:: LinkType + + Object where the keys are Interface ID ``i`` and the values describe the link associated + with interface ``i`` as one of: + + ``"direct"`` + Direct physical connection. + + ``"multihop"`` + Connection with local routing/switching. + + ``"opennet"`` + Connection overlayed over publicly routed Internet. + +.. option:: Hops + + Object where the keys are Interface ID ``i`` and the values are objects with: + + .. option:: Intra = map[interface-id j]: number + + Number of internal hops (e.g. number of AS-internal IP routers) between interface ``i`` and + interface ``j``. + +.. option:: Note = + + A free form string to communicate interesting/important information to other network operators. + + +.. _control-conf-duration: + +Duration Format +--------------- + +Where duration values are loaded from configuration options, the following format is expected: + +.. code-block:: + + [\-0-9]+(y|w|d|h|m|s|ms|us|µs|ns) + +The unit suffixes have their usual meaning of ``y`` year, ``w`` week, ``d`` day, ``h`` hour, +``m`` minute, ``s`` second, ``ms`` millisecond, ``us`` or ``µs`` microsecond, and ``ns`` nanosecond. + +Mixed unit durations are not supported (e.g. ``1h10m10s`` is not supported). +The long duration units are simple factors, not calendar offsets: + +- ``d`` is always 24 hours +- ``w`` is always 7 days +- ``y`` is always 365 days + + Port table ========== @@ -12,7 +808,26 @@ Metrics .. include:: ./control/metrics.rst +.. _control-http-api: + HTTP API ======== .. include:: ./control/http-api.rst + +.. _control-rest-api: + +REST API +======== + +The REST API described by the OpenAPI specification :file-ref:`spec/control.gen.yml` +is exposed by :program:`control` on the address defined by +:option:`api.addr `. + +Note that this is **separate** from the partially redundant, ad hoc :ref:`control-http-api`. + +Specification +------------- + +.. openapi:: /../spec/control.gen.yml + :group: diff --git a/doc/manuals/control/http-api.rst b/doc/manuals/control/http-api.rst index 39012418d..54a39a950 100644 --- a/doc/manuals/control/http-api.rst +++ b/doc/manuals/control/http-api.rst @@ -1,3 +1,9 @@ +.. warning:: + Note that this ad hoc HTTP API is **separate** from the partially redundant + :ref:`control-rest-api`. + The REST API should be preferred. + This HTTP API will be phased out. + The HTTP API is exposed by the ``control`` application on the IP address and port of the ``metrics.prometheus`` configuration setting. diff --git a/doc/manuals/router.rst b/doc/manuals/router.rst index 7bebbc39f..12b079620 100644 --- a/doc/manuals/router.rst +++ b/doc/manuals/router.rst @@ -14,6 +14,14 @@ Command Line Reference .. program:: router +Synopsis +-------- + +:program:`router` [:option:`--config \ ` | :option:`help ` | :option:`version `] + +Options +------- + .. option:: --config Specifes the :ref:`configuration file ` and starts the router. @@ -143,6 +151,7 @@ The :program:`router` loads the forwarding secret keys ``master0.key``/``master1 The key files contain a base64-encoded high-entropy random string. The keys should be exactly 16 bytes long (corresponding to a base64 encoding of 24 bytes with two trailing pad bytes ``==``). +These keys must be identical to the :ref:`corresponding keys used by the control service `. .. note:: The :program:`router` and :doc:`control` currently use these keys as input for PBKDF2 to generate diff --git a/doc/manuals/router/http-api.rst b/doc/manuals/router/http-api.rst index ebcc0bfe1..4a9066d98 100644 --- a/doc/manuals/router/http-api.rst +++ b/doc/manuals/router/http-api.rst @@ -6,3 +6,6 @@ The HTTP API does not support user authentication or HTTPS. Applications will wa this port or bind to a loopback address. The :program:`router` currently only supports the :ref:`common HTTP API `. + +.. TODO + The router DOES appear to have a partially redundant OpenAPI as well! diff --git a/doc/overview.rst b/doc/overview.rst index f17a60446..93203eb4c 100644 --- a/doc/overview.rst +++ b/doc/overview.rst @@ -19,6 +19,8 @@ important for the Internet to perform well, lie outside the scope of SCION. Concepts ======== +.. _overview-isds: + Isolation Domains (ISDs) ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,6 +61,27 @@ The endpoint local address is not used for inter-domain routing or forwarding, d globally unique, and can thus be an IPv4, IPv6, or MAC address, for example. A SCION endpoint address is the ``ISD-AS,local address`` 3-tuple. +.. _overview-as-roles: + +AS Roles +^^^^^^^^ + +Some ASes have special roles in their ISD. +The TRC of an ISD declares which AS has which designated roles. +An AS can have multiple, or all, of these roles at the same time. + +- **Core ASes** have a special role in routing. + They are at the top of their ISD's routing domain, and connect their customer ASes to the outside. + Core ASes participate in the inter-ISD *and* the intra-ISD path-exploration process (see + `Routing`_ below). + +- **Certification authorities (CAs)** are responsible for issuing AS certificates to other ASes + and/or themselves. + +- **Voting ASes** and **Authoritative ASes** are related to the update mechanism for TRCs. + Voting ASes can "vote" to accept an updated TRC. + Authoritative ASes always have the latest TRCs of the ISD and start the announcement of a TRC update. + .. _overview-link-types: Link Types diff --git a/doc/protocols/scion-header.rst b/doc/protocols/scion-header.rst index 81a7ada87..db71176cc 100644 --- a/doc/protocols/scion-header.rst +++ b/doc/protocols/scion-header.rst @@ -245,6 +245,9 @@ E without further forwarding the request along the path. Use cases that require multiple routers/hops on the path to process a packet should instead rely on a **hop-by-hop extension**. + +.. _scion-path-exptime: + ExpTime Expiry time of a hop field. The field is 1-byte long, thus there are 256 different values available to express an expiration time. The expiration diff --git a/doc/requirements.in b/doc/requirements.in index 1a9af83dd..880a8fd66 100644 --- a/doc/requirements.in +++ b/doc/requirements.in @@ -2,3 +2,4 @@ Sphinx recommonmark sphinx-autobuild sphinx-rtd-theme +sphinxcontrib-openapi diff --git a/doc/requirements.txt b/doc/requirements.txt index adac82314..05ea6e77e 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -8,6 +8,10 @@ alabaster==0.7.13 \ --hash=sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3 \ --hash=sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2 # via sphinx +attrs==22.2.0 \ + --hash=sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836 \ + --hash=sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99 + # via jsonschema babel==2.11.0 \ --hash=sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe \ --hash=sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6 @@ -114,12 +118,17 @@ commonmark==0.9.1 \ --hash=sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60 \ --hash=sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9 # via recommonmark +deepmerge==1.1.0 \ + --hash=sha256:4c27a0db5de285e1a7ceac7dbc1531deaa556b627dea4900c8244581ecdfea2d \ + --hash=sha256:59e6ef80b77dc52af3882a1ea78da22bcfc91ae9cdabc0c80729049fe295ff8b + # via sphinxcontrib-openapi docutils==0.18.1 \ --hash=sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c \ --hash=sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06 # via # recommonmark # sphinx + # sphinx-mdinclude # sphinx-rtd-theme idna==3.4 \ --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ @@ -133,10 +142,18 @@ importlib-metadata==6.0.0 \ --hash=sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad \ --hash=sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d # via sphinx +importlib-resources==5.12.0 \ + --hash=sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6 \ + --hash=sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a + # via jsonschema jinja2==3.1.2 \ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 # via sphinx +jsonschema==4.17.3 \ + --hash=sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d \ + --hash=sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6 + # via sphinxcontrib-openapi livereload==2.6.3 \ --hash=sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869 \ --hash=sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4 @@ -193,18 +210,103 @@ markupsafe==2.1.2 \ --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 # via jinja2 +mistune==2.0.5 \ + --hash=sha256:0246113cb2492db875c6be56974a7c893333bf26cd92891c85f63151cee09d34 \ + --hash=sha256:bad7f5d431886fcbaf5f758118ecff70d31f75231b34024a1341120340a65ce8 + # via sphinx-mdinclude packaging==23.0 \ --hash=sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2 \ --hash=sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97 # via sphinx +picobox==2.2.0 \ + --hash=sha256:0a14f8fae386a46e61671a3ce16e0d54d24fb8f15169b0971483228a3e274622 \ + --hash=sha256:c446ea34b5ee396ab8dc7cbed8f036e73e52403593088656b9b45b7d6382c926 + # via sphinxcontrib-openapi +pkgutil-resolve-name==1.3.10 \ + --hash=sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174 \ + --hash=sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e + # via jsonschema pygments==2.14.0 \ --hash=sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297 \ --hash=sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717 - # via sphinx + # via + # sphinx + # sphinx-mdinclude +pyrsistent==0.19.3 \ + --hash=sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8 \ + --hash=sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440 \ + --hash=sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a \ + --hash=sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c \ + --hash=sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3 \ + --hash=sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393 \ + --hash=sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9 \ + --hash=sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da \ + --hash=sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf \ + --hash=sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64 \ + --hash=sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a \ + --hash=sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3 \ + --hash=sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98 \ + --hash=sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2 \ + --hash=sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8 \ + --hash=sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf \ + --hash=sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc \ + --hash=sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7 \ + --hash=sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28 \ + --hash=sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2 \ + --hash=sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b \ + --hash=sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a \ + --hash=sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64 \ + --hash=sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19 \ + --hash=sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1 \ + --hash=sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9 \ + --hash=sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c + # via jsonschema pytz==2022.7.1 \ --hash=sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0 \ --hash=sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a # via babel +pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via sphinxcontrib-openapi recommonmark==0.7.1 \ --hash=sha256:1b1db69af0231efce3fa21b94ff627ea33dee7079a01dd0a7f8482c3da148b3f \ --hash=sha256:bdb4db649f2222dcd8d2d844f0006b958d627f732415d399791ee436a3686d67 @@ -216,7 +318,9 @@ requests==2.28.2 \ six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 - # via livereload + # via + # livereload + # sphinxcontrib-httpdomain snowballstemmer==2.2.0 \ --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \ --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a @@ -229,10 +333,16 @@ sphinx==6.1.3 \ # recommonmark # sphinx-autobuild # sphinx-rtd-theme + # sphinxcontrib-httpdomain + # sphinxcontrib-openapi sphinx-autobuild==2021.3.14 \ --hash=sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac \ --hash=sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05 # via -r requirements.in +sphinx-mdinclude==0.5.3 \ + --hash=sha256:02afadf4597aecf8255a702956eff5b8c5cb9658ea995c3d361722d2ed78cca9 \ + --hash=sha256:2998e3d18b3022c9983d1b72191fe37e25ffccd54165cbe3acb22cceedd91af4 + # via sphinxcontrib-openapi sphinx-rtd-theme==1.2.0 \ --hash=sha256:a0d8bd1a2ed52e0b338cbe19c4b2eef3c5e7a048769753dac6a9f059c7b641b8 \ --hash=sha256:f823f7e71890abe0ac6aaa6013361ea2696fc8d3e1fa798f463e82bdb77eeff2 @@ -249,6 +359,10 @@ sphinxcontrib-htmlhelp==2.0.1 \ --hash=sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff \ --hash=sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903 # via sphinx +sphinxcontrib-httpdomain==1.8.1 \ + --hash=sha256:21eefe1270e4d9de8d717cc89ee92cc4871b8736774393bafc5e38a6bb77b1d5 \ + --hash=sha256:6c2dfe6ca282d75f66df333869bb0ce7331c01b475db6809ff9d107b7cdfe04b + # via sphinxcontrib-openapi sphinxcontrib-jquery==2.0.0 \ --hash=sha256:8fb65f6dba84bf7bcd1aea1f02ab3955ac34611d838bcc95d4983b805b234daa \ --hash=sha256:ed47fa425c338ffebe3c37e1cdb56e30eb806116b85f01055b158c7057fdb995 @@ -257,6 +371,10 @@ sphinxcontrib-jsmath==1.0.1 \ --hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \ --hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8 # via sphinx +sphinxcontrib-openapi==0.8.1 \ + --hash=sha256:04fcf87c259345162a504ce3dfee0f71389f507c3797798dc531c7748995b4eb \ + --hash=sha256:45ecad2a98e304d3665c133ea08a7083a2b5d86e75c6b64c60389240b3927ad5 + # via -r requirements.in sphinxcontrib-qthelp==1.0.3 \ --hash=sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72 \ --hash=sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6 @@ -285,7 +403,9 @@ urllib3==1.26.14 \ zipp==3.14.0 \ --hash=sha256:188834565033387710d046e3fe96acfc9b5e86cbca7f39ff69cf21a4128198b7 \ --hash=sha256:9e5421e176ef5ab4c0ad896624e87a7b2f07aca746c9b2aa305952800cb8eecb - # via importlib-metadata + # via + # importlib-metadata + # importlib-resources # WARNING: The following packages were not pinned, but pip requires them to be # pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag. From 49b3f90cb1a946fa64f7fbd7eee2dde4351a1e0d Mon Sep 17 00:00:00 2001 From: rohrerj <26304001+rohrerj@users.noreply.github.com> Date: Fri, 4 Aug 2023 18:35:49 +0200 Subject: [PATCH 044/255] router: configuration for async packet processing (#4374) Implement configuration for the border router processing structure added in #4351. This is implementation part two of three described in the design document (#4339, doc/dev/design/BorderRouter.rst). --- doc/manuals/router.rst | 35 +++++++++++++++++++++++ private/underlay/conn/conn.go | 2 +- router/cmd/router/main.go | 9 ++++-- router/config/BUILD.bazel | 6 +++- router/config/config.go | 54 +++++++++++++++++++++++++++++++++++ router/config/sample.go | 38 ++++++++++++++++++++++++ router/connector.go | 10 +++---- router/dataplane.go | 21 ++++---------- 8 files changed, 151 insertions(+), 24 deletions(-) create mode 100644 router/config/sample.go diff --git a/doc/manuals/router.rst b/doc/manuals/router.rst index 12b079620..8ad652640 100644 --- a/doc/manuals/router.rst +++ b/doc/manuals/router.rst @@ -125,6 +125,41 @@ considers the following options. If this is a relative path, it is interpreted as relative to the current working directory of the program (i.e. **not** relative to the location of this .toml configuration file). +.. object:: router + + .. option:: router.receive_buffer_size = (Default: 0) + + The receive buffer size in bytes. 0 means use system default. + + .. option:: router.send_buffer_size = (Default: 0) + + The send buffer size in bytes. 0 means use system default. + + .. option:: router.num_processors = (Default: GOMAXPROCS) + + Number of goroutines started for SCION packets processing. + These goroutines make the routing decision for the SCION packets by inspecting, validating and + updating the path information in the packet header. Packets are processed asynchronously from the + corresponding read/write operations on the individual interface sockets. + + `Goroutines `_ + are the Go pramming language's light-weight user-space concurrency primitives. Go's runtime schedules + goroutines on top of a fixed number of kernel threads. The number of kernel threads is controlled by + the ``GOMAXPROCS`` environment variable. See also the `go runtime documentation `_. + + By default, the router uses ``GOMAXPROCS`` packet processor goroutines, i.e. exactly one goroutine for + each kernel thread created by the runtime. + + .. option:: router.num_slow_processors = (Default: 1) + + Number of goroutines started for the slow-path processing. This feature will be implemented soon. Currently + this setting has no effect. + + .. option:: router.batch_size = (Default: 256) + + The batch size used by the receiver and forwarder to + read or write from / to the network socket. + .. _router-conf-topo: topology.json diff --git a/private/underlay/conn/conn.go b/private/underlay/conn/conn.go index a87724c83..c56c30225 100644 --- a/private/underlay/conn/conn.go +++ b/private/underlay/conn/conn.go @@ -214,7 +214,7 @@ func (cc *connUDPBase) initConnUDP(network string, laddr, raddr *net.UDPAddr, cf } // Set and confirm receive buffer size - { + if cfg.ReceiveBufferSize != 0 { before, err := sockctrl.GetsockoptInt(c, syscall.SOL_SOCKET, syscall.SO_RCVBUF) if err != nil { return serrors.WrapStr("Error getting SO_RCVBUF socket option (before)", err, diff --git a/router/cmd/router/main.go b/router/cmd/router/main.go index ccc765f93..c2ecdbdbf 100644 --- a/router/cmd/router/main.go +++ b/router/cmd/router/main.go @@ -60,6 +60,8 @@ func realMain(ctx context.Context) error { DataPlane: router.DataPlane{ Metrics: metrics, }, + ReceiveBufferSize: globalCfg.Router.ReceiveBufferSize, + SendBufferSize: globalCfg.Router.SendBufferSize, } iaCtx := &control.IACtx{ Config: controlConfig, @@ -121,8 +123,11 @@ func realMain(ctx context.Context) error { }) g.Go(func() error { defer log.HandlePanic() - runConfig := &router.RunConfig{} - runConfig.LoadDefaults() + runConfig := &router.RunConfig{ + NumProcessors: globalCfg.Router.NumProcessors, + NumSlowPathProcessors: globalCfg.Router.NumSlowPathProcessors, + BatchSize: globalCfg.Router.BatchSize, + } if err := dp.DataPlane.Run(errCtx, runConfig); err != nil { return serrors.WrapStr("running dataplane", err) } diff --git a/router/config/BUILD.bazel b/router/config/BUILD.bazel index 7a6b13196..7538118ee 100644 --- a/router/config/BUILD.bazel +++ b/router/config/BUILD.bazel @@ -2,11 +2,15 @@ load("//tools/lint:go.bzl", "go_library", "go_test") go_library( name = "go_default_library", - srcs = ["config.go"], + srcs = [ + "config.go", + "sample.go", + ], importpath = "github.com/scionproto/scion/router/config", visibility = ["//visibility:public"], deps = [ "//pkg/log:go_default_library", + "//pkg/private/serrors:go_default_library", "//private/config:go_default_library", "//private/env:go_default_library", "//private/mgmtapi:go_default_library", diff --git a/router/config/config.go b/router/config/config.go index b40818d6e..f3376a302 100644 --- a/router/config/config.go +++ b/router/config/config.go @@ -18,8 +18,10 @@ package config import ( "io" + "runtime" "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/private/config" "github.com/scionproto/scion/private/env" api "github.com/scionproto/scion/private/mgmtapi" @@ -33,6 +35,55 @@ type Config struct { Logging log.Config `toml:"log,omitempty"` Metrics env.Metrics `toml:"metrics,omitempty"` API api.Config `toml:"api,omitempty"` + Router RouterConfig `toml:"router,omitempty"` +} + +type RouterConfig struct { + ReceiveBufferSize int `toml:"receive_buffer_size,omitempty"` + SendBufferSize int `toml:"send_buffer_size,omitempty"` + NumProcessors int `toml:"num_processors,omitempty"` + NumSlowPathProcessors int `toml:"num_slow_processors,omitempty"` + BatchSize int `toml:"batch_size,omitempty"` +} + +func (cfg *RouterConfig) ConfigName() string { + return "router" +} + +func (cfg *RouterConfig) Validate() error { + if cfg.ReceiveBufferSize < 0 { + return serrors.New("Provided router config is invalid. ReceiveBufferSize < 0") + } + if cfg.SendBufferSize < 0 { + return serrors.New("Provided router config is invalid. SendBufferSize < 0") + } + if cfg.BatchSize < 1 { + return serrors.New("Provided router config is invalid. BatchSize < 1") + } + if cfg.NumProcessors < 0 { + return serrors.New("Provided router config is invalid. NumProcessors < 0") + } + if cfg.NumSlowPathProcessors < 1 { + return serrors.New("Provided router config is invalid. NumSlowPathProcessors < 1") + } + + return nil +} + +func (cfg *RouterConfig) InitDefaults() { + if cfg.NumProcessors == 0 { + cfg.NumProcessors = runtime.GOMAXPROCS(0) + } + if cfg.NumSlowPathProcessors == 0 { + cfg.NumSlowPathProcessors = 1 + } + if cfg.BatchSize == 0 { + cfg.BatchSize = 256 + } +} + +func (cfg *RouterConfig) Sample(dst io.Writer, path config.Path, ctx config.CtxMap) { + config.WriteString(dst, routerConfigSample) } func (cfg *Config) InitDefaults() { @@ -42,6 +93,7 @@ func (cfg *Config) InitDefaults() { &cfg.Logging, &cfg.Metrics, &cfg.API, + &cfg.Router, ) } @@ -52,6 +104,7 @@ func (cfg *Config) Validate() error { &cfg.Logging, &cfg.Metrics, &cfg.API, + &cfg.Router, ) } @@ -62,5 +115,6 @@ func (cfg *Config) Sample(dst io.Writer, path config.Path, _ config.CtxMap) { &cfg.Logging, &cfg.Metrics, &cfg.API, + &cfg.Router, ) } diff --git a/router/config/sample.go b/router/config/sample.go new file mode 100644 index 000000000..43bc647a9 --- /dev/null +++ b/router/config/sample.go @@ -0,0 +1,38 @@ +// Copyright 2023 ETH Zurich +// +// 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 config + +const routerConfigSample = ` +# The receive buffer size in bytes. 0 means use system default. +# (default 0) +receive_buffer_size = 0 + +# The send buffer size in bytes. 0 means use system default. +# (default 0) +send_buffer_size = 0 + +# The number of fast-path processors. +# (default GOMAXPROCS) +num_processors = 8 + +# The number of slow-path processors. +# (default 1) +num_slow_processors = 1 + +# The batch size used by the receiver and forwarder to +# read or write from / to the network socket. +# (default 256) +batch_size = 256 +` diff --git a/router/connector.go b/router/connector.go index 6944e75b2..7b744b2c4 100644 --- a/router/connector.go +++ b/router/connector.go @@ -27,9 +27,6 @@ import ( "github.com/scionproto/scion/router/control" ) -// receiveBufferSize is the size of receive buffers used by the router. -const receiveBufferSize = 1 << 20 - // Connector implements the Dataplane API of the router control process. It sets // up connections for the DataPlane. type Connector struct { @@ -40,6 +37,9 @@ type Connector struct { internalInterfaces []control.InternalInterface externalInterfaces map[uint16]control.ExternalInterface siblingInterfaces map[uint16]control.SiblingInterface + + ReceiveBufferSize int + SendBufferSize int } var errMultiIA = serrors.New("different IA not allowed") @@ -65,7 +65,7 @@ func (c *Connector) AddInternalInterface(ia addr.IA, local net.UDPAddr) error { return serrors.WithCtx(errMultiIA, "current", c.ia, "new", ia) } connection, err := conn.New(&local, nil, - &conn.Config{ReceiveBufferSize: receiveBufferSize}) + &conn.Config{ReceiveBufferSize: c.ReceiveBufferSize, SendBufferSize: c.SendBufferSize}) if err != nil { return err } @@ -130,7 +130,7 @@ func (c *Connector) AddExternalInterface(localIfID common.IFIDType, link control } connection, err := conn.New(link.Local.Addr, link.Remote.Addr, - &conn.Config{ReceiveBufferSize: receiveBufferSize}) + &conn.Config{ReceiveBufferSize: c.ReceiveBufferSize, SendBufferSize: c.SendBufferSize}) if err != nil { return err } diff --git a/router/dataplane.go b/router/dataplane.go index 60f2001c5..609ba3358 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -27,7 +27,6 @@ import ( "math/big" "net" "net/netip" - "runtime" "strconv" "sync" "time" @@ -458,11 +457,6 @@ func (d *DataPlane) AddNextHopBFD(ifID uint16, src, dst *net.UDPAddr, cfg contro return d.addBFDController(ifID, s, cfg, m) } -type RunConfig struct { - NumProcessors int - BatchSize int -} - func max(a int, b int) int { if a > b { return a @@ -470,6 +464,12 @@ func max(a int, b int) int { return b } +type RunConfig struct { + NumProcessors int + NumSlowPathProcessors int + BatchSize int +} + func (d *DataPlane) Run(ctx context.Context, cfg *RunConfig) error { d.mtx.Lock() d.running = true @@ -513,15 +513,6 @@ func (d *DataPlane) Run(ctx context.Context, cfg *RunConfig) error { return nil } -// loadDefaults sets the default configuration for the number of -// processors and the batch size -func (r *RunConfig) LoadDefaults() { - // TODO(rohrerj) move this logic to configuration in configuration PR - r.NumProcessors = runtime.GOMAXPROCS(0) - r.BatchSize = 256 - -} - // initializePacketPool calculates the size of the packet pool based on the // current dataplane settings and allocates all the buffers func (d *DataPlane) initPacketPool(cfg *RunConfig, processorQueueSize int) { From 24cfafcf4bb1144daaf4e5d50b6abbc0e075abc7 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Tue, 8 Aug 2023 08:52:19 +0200 Subject: [PATCH 045/255] build: allow go test ./... to run without errors (#4375) Ensure `go test ./...` runs without errors out-of-the-box. To this end, we guard the acceptance tests behind a skip tag because they require a special setup and are not meant to be run as regular unit tests. We also add stub packages for the linter tests. --- acceptance/topo_cs_reload/reload_test.go | 5 +++ acceptance/topo_daemon_reload/reload_test.go | 5 +++ .../testdata/src/fake/lib/slog/slog.go | 20 ++++++++++++ .../src/github.com/scionproto/scion/pkg/log | 1 - .../scionproto/scion/pkg/log/log.go | 32 +++++++++++++++++++ .../testdata/src/fake/serrors/serrors.go | 19 +++++++++++ .../scion/pkg/private/serrors/serrors.go | 22 +++++++++++++ 7 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tools/lint/logctxcheck/testdata/src/fake/lib/slog/slog.go delete mode 120000 tools/lint/logctxcheck/testdata/src/github.com/scionproto/scion/pkg/log create mode 100644 tools/lint/logctxcheck/testdata/src/github.com/scionproto/scion/pkg/log/log.go create mode 100644 tools/lint/serrorscheck/testdata/src/fake/serrors/serrors.go create mode 100644 tools/lint/serrorscheck/testdata/src/github.com/scionproto/scion/pkg/private/serrors/serrors.go diff --git a/acceptance/topo_cs_reload/reload_test.go b/acceptance/topo_cs_reload/reload_test.go index 55e30c924..790f4a012 100644 --- a/acceptance/topo_cs_reload/reload_test.go +++ b/acceptance/topo_cs_reload/reload_test.go @@ -22,6 +22,7 @@ import ( "net/http" "os" "os/exec" + "strings" "testing" "time" @@ -42,6 +43,10 @@ var ( ) func TestPSTopoReload(t *testing.T) { + if !strings.HasSuffix(os.Getenv("TEST_TARGET"), "go_default_test") { + t.Skip("This test only runs as bazel unit test") + } + // BUG(matzf): teardown is not called when setup fails. Rewrite with T.Cleanup and T.Tempdir s := setupTest(t) defer s.teardownTest(t) diff --git a/acceptance/topo_daemon_reload/reload_test.go b/acceptance/topo_daemon_reload/reload_test.go index 7a39ce232..243cb133a 100644 --- a/acceptance/topo_daemon_reload/reload_test.go +++ b/acceptance/topo_daemon_reload/reload_test.go @@ -21,6 +21,7 @@ import ( "net/http" "os" "os/exec" + "strings" "testing" "time" @@ -31,6 +32,10 @@ import ( ) func TestSDTopoReload(t *testing.T) { + if !strings.HasSuffix(os.Getenv("TEST_TARGET"), "go_default_test") { + t.Skip("This test only runs as bazel unit test") + } + defer teardownTest(t) setupTest(t) diff --git a/tools/lint/logctxcheck/testdata/src/fake/lib/slog/slog.go b/tools/lint/logctxcheck/testdata/src/fake/lib/slog/slog.go new file mode 100644 index 000000000..42bf45c33 --- /dev/null +++ b/tools/lint/logctxcheck/testdata/src/fake/lib/slog/slog.go @@ -0,0 +1,20 @@ +// Copyright 2023 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 slog is a stub for testing +package slog + +func Debug(string, ...any) {} +func Info(string, ...any) {} +func Error(string, ...any) {} diff --git a/tools/lint/logctxcheck/testdata/src/github.com/scionproto/scion/pkg/log b/tools/lint/logctxcheck/testdata/src/github.com/scionproto/scion/pkg/log deleted file mode 120000 index e86440b89..000000000 --- a/tools/lint/logctxcheck/testdata/src/github.com/scionproto/scion/pkg/log +++ /dev/null @@ -1 +0,0 @@ -../../../../../../../../../pkg/log \ No newline at end of file diff --git a/tools/lint/logctxcheck/testdata/src/github.com/scionproto/scion/pkg/log/log.go b/tools/lint/logctxcheck/testdata/src/github.com/scionproto/scion/pkg/log/log.go new file mode 100644 index 000000000..14c664ba9 --- /dev/null +++ b/tools/lint/logctxcheck/testdata/src/github.com/scionproto/scion/pkg/log/log.go @@ -0,0 +1,32 @@ +// Copyright 2023 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 log is a stub for the actual log package. It allows the logctxcheck +// analyzer tests to run. +package log + +import "context" + +func Debug(string, ...any) {} +func Info(string, ...any) {} +func Error(string, ...any) {} +func New(...any) Logger { return nil } +func FromCtx(context.Context) Logger { return nil } +func Root() Logger { return nil } + +type Logger interface { + Debug(string, ...any) + Info(string, ...any) + Error(string, ...any) +} diff --git a/tools/lint/serrorscheck/testdata/src/fake/serrors/serrors.go b/tools/lint/serrorscheck/testdata/src/fake/serrors/serrors.go new file mode 100644 index 000000000..4e1a69166 --- /dev/null +++ b/tools/lint/serrorscheck/testdata/src/fake/serrors/serrors.go @@ -0,0 +1,19 @@ +// Copyright 2023 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 serrors is a stub for testing +package serrors + +func New(string, ...any) error { return nil } +func Wrap(error, error, ...any) error { return nil } diff --git a/tools/lint/serrorscheck/testdata/src/github.com/scionproto/scion/pkg/private/serrors/serrors.go b/tools/lint/serrorscheck/testdata/src/github.com/scionproto/scion/pkg/private/serrors/serrors.go new file mode 100644 index 000000000..95b5ffb8a --- /dev/null +++ b/tools/lint/serrorscheck/testdata/src/github.com/scionproto/scion/pkg/private/serrors/serrors.go @@ -0,0 +1,22 @@ +// Copyright 2023 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 serrors is a stub for the actual serrors package. It allows the +// serrorscheck analyzer tests to run. +package serrors + +func New(string, ...any) error { return nil } +func Wrap(error, error, ...any) error { return nil } +func WrapStr(error, string, ...any) error { return nil } +func WithCtx(error, ...any) error { return nil } From 4096d879b05a0a7e287bfb79590941facdf40bf4 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Thu, 10 Aug 2023 21:46:35 +0200 Subject: [PATCH 046/255] build: support fedora (#4371) 1 . Update the scripts in tools/ so the necessary packages are installed (in the right order). 2 . Bottleneck references the sqlite lib through a single source file so it's easy to use different implementations of that lib. 3 . Replace mattn_sqlite with modenrc_sqlite to remove dependency on a specific version of glibc (which breaks integration tests). Also did some minor makefile simplifications: no need to "make go-mod-tidy" and "make go_deps.blz" explicitly. It happens as needed upon "make gazelle". --- .bazelrc | 5 + .buildkite/pipeline.yml | 2 +- BUILD.bazel | 76 +++++++++++- Makefile | 23 ++-- doc/dev/dependencies.rst | 7 +- doc/dev/setup.rst | 19 ++- go.mod | 15 ++- go.sum | 36 +++++- go_deps.bzl | 116 +++++++++++++++++- .../LICENSE | 10 +- .../com_github_remyoudompheng_bigfft/LICENSE | 27 ++++ licenses/data/org_modernc_libc/LICENSE | 27 ++++ licenses/data/org_modernc_libc/LICENSE-GO | 27 ++++ .../honnef.co/go/netdb/LICENSE | 20 +++ licenses/data/org_modernc_mathutil/LICENSE | 27 ++++ .../org_modernc_mathutil/mersenne/LICENSE | 27 ++++ licenses/data/org_modernc_memory/LICENSE | 27 ++++ licenses/data/org_modernc_memory/LICENSE-GO | 27 ++++ .../data/org_modernc_memory/LICENSE-MMAP-GO | 25 ++++ licenses/data/org_modernc_sqlite/LICENSE | 26 ++++ .../data/org_modernc_sqlite/SQLITE-LICENSE | 25 ++++ nogo.json | 11 +- private/storage/beacon/sqlite/BUILD.bazel | 1 - private/storage/beacon/sqlite/db.go | 2 - private/storage/db/BUILD.bazel | 2 + private/storage/db/sqlite.go | 10 +- private/storage/db/sqlite_mattn.go | 41 +++++++ private/storage/db/sqlite_modernc.go | 48 ++++++++ .../storage/drkey/level1/sqlite/BUILD.bazel | 1 - private/storage/drkey/level1/sqlite/db.go | 2 - .../storage/drkey/level2/sqlite/BUILD.bazel | 1 - private/storage/drkey/level2/sqlite/db.go | 2 - .../storage/drkey/secret/sqlite/BUILD.bazel | 1 - private/storage/drkey/secret/sqlite/db.go | 2 - private/storage/path/sqlite/BUILD.bazel | 1 - private/storage/path/sqlite/sqlite.go | 2 - private/storage/trust/sqlite/BUILD.bazel | 1 - private/storage/trust/sqlite/db.go | 2 - tools/dc | 2 +- tools/env/rhel/deps | 3 +- tools/env/rhel/pkgs.txt | 10 ++ tools/install_deps | 2 +- tools/update_testdata.sh | 6 +- 43 files changed, 683 insertions(+), 64 deletions(-) rename licenses/data/{com_github_mattn_go_sqlite3 => com_github_dustin_go_humanize}/LICENSE (84%) create mode 100644 licenses/data/com_github_remyoudompheng_bigfft/LICENSE create mode 100644 licenses/data/org_modernc_libc/LICENSE create mode 100644 licenses/data/org_modernc_libc/LICENSE-GO create mode 100644 licenses/data/org_modernc_libc/honnef.co/go/netdb/LICENSE create mode 100644 licenses/data/org_modernc_mathutil/LICENSE create mode 100644 licenses/data/org_modernc_mathutil/mersenne/LICENSE create mode 100644 licenses/data/org_modernc_memory/LICENSE create mode 100644 licenses/data/org_modernc_memory/LICENSE-GO create mode 100644 licenses/data/org_modernc_memory/LICENSE-MMAP-GO create mode 100644 licenses/data/org_modernc_sqlite/LICENSE create mode 100644 licenses/data/org_modernc_sqlite/SQLITE-LICENSE create mode 100644 private/storage/db/sqlite_mattn.go create mode 100644 private/storage/db/sqlite_modernc.go create mode 100644 tools/env/rhel/pkgs.txt diff --git a/.bazelrc b/.bazelrc index 610c9114f..0b4fa25f9 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,5 +1,6 @@ ### common options for all subcommands (help, query, build, ...) common --show_timestamps + # connect to buchgr/bazel-remote cache # These flags can unfortunately not be specified for `common`, as they are not accepted by all subcommands (help, version, dump) build --remote_cache=grpc://localhost:9092 --experimental_remote_downloader=grpc://localhost:9092 @@ -14,6 +15,10 @@ build --java_runtime_version=remotejdk_11 # disable legacy_create_init for py_binary, py_test etc. This may eventually become the default. build --incompatible_default_to_explicit_init_py +# include one of "--define gotags=sqlite_mattn" or "--define gotags=sqlite_modernc" +# cannot be in common, because query chokes on it. +build --define gotags=sqlite_modernc + ### options for test test --build_tests_only --print_relative_test_log_paths --test_output=errors diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 1979d9ce6..aac4913f2 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -31,8 +31,8 @@ steps: - echo "--- go_deps.bzl" - mkdir -p /tmp/test-artifacts - cp go.mod go.sum go_deps.bzl /tmp/test-artifacts/ + - make go.mod - make go_deps.bzl -B - - make go-mod-tidy - diff -u /tmp/test-artifacts/go.mod go.mod - diff -u /tmp/test-artifacts/go.sum go.sum - diff -u /tmp/test-artifacts/go_deps.bzl go_deps.bzl diff --git a/BUILD.bazel b/BUILD.bazel index 6e8445b1d..ba817ae8f 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -17,7 +17,81 @@ load("@cgrindel_bazel_starlib//updatesrc:defs.bzl", "updatesrc_update_all") # gazelle:exclude doc/** # gazelle:exclude rules_openapi/tools/node_modules/** # gazelle:exclude tools/lint/**/testdata/src/** -gazelle(name = "gazelle") + +# We suport two sqlite implementations: modernc and mattn. Each implementation +# has a corresponding sqlite_.go "driver" in private/storage/db. Which +# driver gets compiled and linked is controled by a go build tag: sqlite_mattn +# or sqlite_modernc. Those are specified on the command line +# with "--define gotags=sqlite_mattn" or "--define gotags=sqlite_modernc" +# (see the build options in .bazelrc). +# +# Unfortunately Gazelle needs to be given these tags explicitly via the builtags +# attribute. So, to ensure consistency we have to translate our two gotags into +# build_tags. To that end, we create two config_setting flags that are +# set in response to matching the gotags value and use them to select the relevant +# tag for gazelle. (The "define_value" attribute of config_setting doesn't define +# anything. It matches a key-value pair from "--define"). +# +# This is simplistic but the complete, by-the-everchanging-bazel-book, solution +# is ludicrously complicated. Go there if and when needed. +config_setting( + name = "sqlite_mattn", + define_values = { + "gotags": "sqlite_mattn", + }, +) + +config_setting( + name = "sqlite_modernc", + define_values = { + "gotags": "sqlite_modernc", + }, +) + +# This is a dummy target so Make can "blaze build --announce_rc +# Where something truly does nothing that we may care about. + +config_setting( + name = "dummy_setting", + define_values = { + "whatever": "whatever", + }, +) + +gazelle( + name = "gazelle", + build_tags = select({ + ":sqlite_modernc": ["sqlite_modernc"], + ":sqlite_mattn": ["sqlite_mattn"], + }), + command = "update", + extra_args = [ + "-mode", + "fix", + "-go_naming_convention", + "go_default_library", + ], +) + +gazelle( + name = "gazelle_diff", + build_tags = select({ + ":sqlite_modernc": ["sqlite_modernc"], + ":sqlite_mattn": ["sqlite_mattn"], + }), + command = "update", + extra_args = [ + "-mode", + "diff", + "-go_naming_convention", + "go_default_library", + ], +) + +gazelle( + name = "gazelle_update_repos", + command = "update-repos", +) go_lint_config( name = "go_lint_config", diff --git a/Makefile b/Makefile index 81dcdb505..e9b251cc3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,4 @@ -.PHONY: all antlr bazel clean docker-images gazelle go-mod-tidy licenses mocks protobuf scion-topo test test-integration write_all_source_files -GAZELLE_MODE?=fix -GAZELLE_DIRS=. +.PHONY: all antlr bazel clean docker-images gazelle go.mod licenses mocks protobuf scion-topo test test-integration write_all_source_files build: bazel @@ -10,7 +8,7 @@ build: bazel # Use NOTPARALLEL to force correct order. # Note: From GNU make 4.4, this still allows building any other targets (e.g. lint) in parallel. .NOTPARALLEL: all -all: go_deps.bzl protobuf mocks gazelle licenses build antlr write_all_source_files +all: go_deps.bzl protobuf mocks gazelle build antlr write_all_source_files licenses clean: bazel clean @@ -28,11 +26,12 @@ test: test-integration: bazel test --config=integration_all -go-mod-tidy: +go.mod: bazel run --config=quiet @go_sdk//:bin/go -- mod tidy go_deps.bzl: go.mod - bazel run --config=quiet //:gazelle -- update-repos -prune -from_file=go.mod -to_macro=go_deps.bzl%go_deps + @# gazelle is run with "-args"; so our arguments are added to those from the gazelle() rule. + bazel run --verbose_failures --config=quiet //:gazelle_update_repos -- -args -prune -from_file=go.mod -to_macro=go_deps.bzl%go_deps @# XXX(matzf): clean up; gazelle update-repose inconsistently inserts blank lines (see bazelbuild/bazel-gazelle#1088). @sed -e '/def go_deps/,$${/^$$/d}' -i go_deps.bzl @@ -57,14 +56,14 @@ protobuf: mocks: tools/gomocks.py -gazelle: - bazel run //:gazelle --config=quiet -- update -mode=$(GAZELLE_MODE) -go_naming_convention go_default_library $(GAZELLE_DIRS) +gazelle: go_deps.bzl + bazel run //:gazelle --verbose_failures --config=quiet licenses: tools/licenses.sh antlr: - antlr/generate.sh $(GAZELLE_MODE) + antlr/generate.sh fix write_all_source_files: bazel run //:write_all_source_files @@ -83,16 +82,18 @@ lint-go: lint-go-gazelle lint-go-bazel lint-go-golangci lint-go-semgrep lint-go-gazelle: $(info ==> $@) - @$(MAKE) -s gazelle GAZELLE_MODE=diff + bazel run //:gazelle_diff --verbose_failures --config=quiet lint-go-bazel: $(info ==> $@) @tools/quiet bazel test --config lint +GO_BUILD_TAGS_ARG=$(shell bazel build --ui_event_filters=-stdout,-stderr --announce_rc --noshow_progress :dummy_setting 2>&1 | grep "'build' options" | sed -n "s/^.*--define gotags=\(\S*\).*/--build-tags \1/p" ) + lint-go-golangci: $(info ==> $@) @if [ -t 1 ]; then tty=true; else tty=false; fi; \ - tools/quiet docker run --tty=$$tty --rm -v golangci-lint-modcache:/go -v golangci-lint-buildcache:/root/.cache -v "${PWD}:/src" -w /src golangci/golangci-lint:v1.50.0 golangci-lint run --config=/src/.golangcilint.yml --timeout=3m --skip-dirs doc ./... + tools/quiet docker run --tty=$$tty --rm -v golangci-lint-modcache:/go -v golangci-lint-buildcache:/root/.cache -v "${PWD}:/src" -w /src golangci/golangci-lint:v1.50.0 golangci-lint run --config=/src/.golangcilint.yml --timeout=3m $(GO_BUILD_TAGS_ARG) --skip-dirs doc ./... lint-go-semgrep: $(info ==> $@) diff --git a/doc/dev/dependencies.rst b/doc/dev/dependencies.rst index 9f236cd13..2ccb8fbd4 100644 --- a/doc/dev/dependencies.rst +++ b/doc/dev/dependencies.rst @@ -22,10 +22,9 @@ Workflow to modify dependencies To add/remove or update dependencies: 1. Modify ``go.mod``, manually or using e.g. ``go get``. -2. ``make go-mod-tidy`` -3. ``make go_deps.bzl`` -4. ``make licenses``, to update the licenses with the new dependency -5. ``make gazelle``, to update the build files that depend on the newly added dependency +2. ``make go_deps.bzl`` +3. ``make licenses``, to update the licenses with the new dependency +4. ``make gazelle``, to update the build files that depend on the newly added dependency .. Warning:: The Go rules for Bazel (rules_go) declares some internally used dependencies. diff --git a/doc/dev/setup.rst b/doc/dev/setup.rst index e1a87a126..53040cec4 100644 --- a/doc/dev/setup.rst +++ b/doc/dev/setup.rst @@ -9,9 +9,9 @@ Prerequisites #. Make sure that you are using a clean and recently updated linux distribution. Distributions that are known to work are: - * **Ubuntu** release 18.04 or later. - * **Fedora** release 38 or later. - * **Amazon** Linux 2. + - **Ubuntu** release 18.04 or later. + - **Fedora** release 38 or later. + - **Amazon** Linux 2. Other Linux environments will usually be fine too, but some of the tooling might need tweaking. If you make things work for other distributions, please update this list. @@ -109,11 +109,22 @@ rejecting your changes. #. Install go. Either follow `the official instructions `_ or check the `Ubuntu specific installation options on the golang wiki `_. +#. Decide which implementation of sqlite you want to use: + + - `mattn`: A cgo implementation. It is well established but makes go + executables dependent on a minimum glibc version. + - `modernc`: A pure go implementation. It does not cause glibc version + issues but is less common. modernc is currently recommended due to + the glibc issue. + #. Build SCION services and tools. .. code-block:: bash - go build -o bin .//cmd/... + go build -o -tags sqlite_ bin .//cmd/... + + where is one of `modernc` or `mattn`. + Tips and Tricks --------------- diff --git a/go.mod b/go.mod index dda75b54f..f7bb61162 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/lestrrat-go/jwx v1.2.25 github.com/lucas-clemente/quic-go v0.29.1 github.com/mattn/go-isatty v0.0.17 - github.com/mattn/go-sqlite3 v1.14.16 + github.com/mattn/go-sqlite3 v1.14.17 github.com/olekukonko/tablewriter v0.0.5 github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.1-0.20180815053127-5633e0862627+incompatible @@ -50,6 +50,7 @@ require ( google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 google.golang.org/protobuf v1.28.1 gopkg.in/yaml.v2 v2.4.0 + modernc.org/sqlite v1.24.0 ) require ( @@ -62,6 +63,7 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/swag v0.21.1 // indirect @@ -75,6 +77,7 @@ require ( github.com/invopop/yaml v0.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jtolds/gls v4.20.0+incompatible // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect github.com/lestrrat-go/blackmagic v1.0.0 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect @@ -97,6 +100,7 @@ require ( github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/smartystreets/assertions v1.2.0 // indirect github.com/spf13/afero v1.9.3 // indirect @@ -115,6 +119,15 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + lukechampine.com/uint128 v1.2.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.22.5 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.0.1 // indirect ) go 1.18 diff --git a/go.sum b/go.sum index b77723de2..4568a3f26 100644 --- a/go.sum +++ b/go.sum @@ -95,6 +95,8 @@ github.com/docker/cli v20.10.20+incompatible h1:lWQbHSHUFs7KraSN2jOJK7zbMS2jNCHI github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/docker v20.10.20+incompatible h1:kH9tx6XO+359d+iAkumyKDc5Q1kOwPuAUaeri48nD6E= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -205,6 +207,7 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -250,6 +253,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= @@ -295,8 +300,8 @@ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPn github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= +github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -370,6 +375,9 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -831,6 +839,30 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= +modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= +modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= +modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.24.0 h1:EsClRIWHGhLTCX44p+Ri/JLD+vFGo0QGjasg2/F9TlI= +modernc.org/sqlite v1.24.0/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= +modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/go_deps.bzl b/go_deps.bzl index af2ee7998..0d1273f01 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -247,6 +247,12 @@ def go_deps(): sum = "h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=", version = "v0.5.0", ) + go_repository( + name = "com_github_dustin_go_humanize", + importpath = "github.com/dustin/go-humanize", + sum = "h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=", + version = "v1.0.1", + ) go_repository( name = "com_github_dvyukov_go_fuzz", importpath = "github.com/dvyukov/go-fuzz", @@ -496,8 +502,8 @@ def go_deps(): go_repository( name = "com_github_google_pprof", importpath = "github.com/google/pprof", - sum = "h1:LR89qFljJ48s990kEKGsk213yIJDPI4205OKOzbURK8=", - version = "v0.0.0-20201218002935-b9804c9f04c2", + sum = "h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=", + version = "v0.0.0-20221118152302-e6195bd50e26", ) go_repository( name = "com_github_google_renameio", @@ -679,6 +685,12 @@ def go_deps(): sum = "h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=", version = "v1.3.0", ) + go_repository( + name = "com_github_kballard_go_shellquote", + importpath = "github.com/kballard/go-shellquote", + sum = "h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=", + version = "v0.0.0-20180428030007-95032a82bc51", + ) go_repository( name = "com_github_kisielk_errcheck", importpath = "github.com/kisielk/errcheck", @@ -697,6 +709,12 @@ def go_deps(): sum = "h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=", version = "v1.15.11", ) + go_repository( + name = "com_github_klauspost_cpuid_v2", + importpath = "github.com/klauspost/cpuid/v2", + sum = "h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=", + version = "v2.2.3", + ) go_repository( name = "com_github_konsorten_go_windows_terminal_sequences", importpath = "github.com/konsorten/go-windows-terminal-sequences", @@ -851,8 +869,8 @@ def go_deps(): go_repository( name = "com_github_mattn_go_sqlite3", importpath = "github.com/mattn/go-sqlite3", - sum = "h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=", - version = "v1.14.16", + sum = "h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=", + version = "v1.14.17", ) go_repository( name = "com_github_matttproud_golang_protobuf_extensions", @@ -1034,6 +1052,12 @@ def go_deps(): sum = "h1:t527LHHE3HmiHrq74QMpNPZpGCIJzTx+apLkMKt4HC0=", version = "v1.0.0", ) + go_repository( + name = "com_github_remyoudompheng_bigfft", + importpath = "github.com/remyoudompheng/bigfft", + sum = "h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=", + version = "v0.0.0-20230129092748-24d4a6f8daec", + ) go_repository( name = "com_github_rogpeppe_go_internal", importpath = "github.com/rogpeppe/go-internal", @@ -1928,6 +1952,12 @@ def go_deps(): sum = "h1:7Chpin9p50NTU8Tb7qk+I11U/IwVXmDhEoSsdccvInE=", version = "v1.9.0", ) + go_repository( + name = "com_lukechampine_uint128", + importpath = "lukechampine.com/uint128", + sum = "h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=", + version = "v1.2.0", + ) go_repository( name = "com_shuralyov_dmitri_gpu_mtl", importpath = "dmitri.shuralyov.com/gpu/mtl", @@ -2168,6 +2198,84 @@ def go_deps(): sum = "h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=", version = "v0.0.0-20220907171357-04be3eba64a2", ) + go_repository( + name = "org_modernc_cc_v3", + importpath = "modernc.org/cc/v3", + sum = "h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=", + version = "v3.40.0", + ) + go_repository( + name = "org_modernc_ccgo_v3", + importpath = "modernc.org/ccgo/v3", + sum = "h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=", + version = "v3.16.13", + ) + go_repository( + name = "org_modernc_ccorpus", + importpath = "modernc.org/ccorpus", + sum = "h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=", + version = "v1.11.6", + ) + go_repository( + name = "org_modernc_httpfs", + importpath = "modernc.org/httpfs", + sum = "h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=", + version = "v1.0.6", + ) + go_repository( + name = "org_modernc_libc", + importpath = "modernc.org/libc", + sum = "h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=", + version = "v1.22.5", + ) + go_repository( + name = "org_modernc_mathutil", + importpath = "modernc.org/mathutil", + sum = "h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=", + version = "v1.5.0", + ) + go_repository( + name = "org_modernc_memory", + importpath = "modernc.org/memory", + sum = "h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=", + version = "v1.5.0", + ) + go_repository( + name = "org_modernc_opt", + importpath = "modernc.org/opt", + sum = "h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=", + version = "v0.1.3", + ) + go_repository( + name = "org_modernc_sqlite", + importpath = "modernc.org/sqlite", + sum = "h1:EsClRIWHGhLTCX44p+Ri/JLD+vFGo0QGjasg2/F9TlI=", + version = "v1.24.0", + ) + go_repository( + name = "org_modernc_strutil", + importpath = "modernc.org/strutil", + sum = "h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=", + version = "v1.1.3", + ) + go_repository( + name = "org_modernc_tcl", + importpath = "modernc.org/tcl", + sum = "h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=", + version = "v1.15.2", + ) + go_repository( + name = "org_modernc_token", + importpath = "modernc.org/token", + sum = "h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=", + version = "v1.0.1", + ) + go_repository( + name = "org_modernc_z", + importpath = "modernc.org/z", + sum = "h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=", + version = "v1.7.3", + ) go_repository( name = "org_uber_go_atomic", importpath = "go.uber.org/atomic", diff --git a/licenses/data/com_github_mattn_go_sqlite3/LICENSE b/licenses/data/com_github_dustin_go_humanize/LICENSE similarity index 84% rename from licenses/data/com_github_mattn_go_sqlite3/LICENSE rename to licenses/data/com_github_dustin_go_humanize/LICENSE index ca458bb39..8d9a94a90 100644 --- a/licenses/data/com_github_mattn_go_sqlite3/LICENSE +++ b/licenses/data/com_github_dustin_go_humanize/LICENSE @@ -1,6 +1,4 @@ -The MIT License (MIT) - -Copyright (c) 2014 Yasuhiro Matsumoto +Copyright (c) 2005-2008 Dustin Sallings Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,8 +7,8 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -19,3 +17,5 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + diff --git a/licenses/data/com_github_remyoudompheng_bigfft/LICENSE b/licenses/data/com_github_remyoudompheng_bigfft/LICENSE new file mode 100644 index 000000000..744875676 --- /dev/null +++ b/licenses/data/com_github_remyoudompheng_bigfft/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/org_modernc_libc/LICENSE b/licenses/data/org_modernc_libc/LICENSE new file mode 100644 index 000000000..0c6500bc3 --- /dev/null +++ b/licenses/data/org_modernc_libc/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2017 The Libc Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the names of the authors nor the names of the +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/org_modernc_libc/LICENSE-GO b/licenses/data/org_modernc_libc/LICENSE-GO new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/licenses/data/org_modernc_libc/LICENSE-GO @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/org_modernc_libc/honnef.co/go/netdb/LICENSE b/licenses/data/org_modernc_libc/honnef.co/go/netdb/LICENSE new file mode 100644 index 000000000..ddd6ddd72 --- /dev/null +++ b/licenses/data/org_modernc_libc/honnef.co/go/netdb/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2012 Dominik Honnef + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/licenses/data/org_modernc_mathutil/LICENSE b/licenses/data/org_modernc_mathutil/LICENSE new file mode 100644 index 000000000..128a1b64a --- /dev/null +++ b/licenses/data/org_modernc_mathutil/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The mathutil Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the names of the authors nor the names of the +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/org_modernc_mathutil/mersenne/LICENSE b/licenses/data/org_modernc_mathutil/mersenne/LICENSE new file mode 100644 index 000000000..4fa2a1f4f --- /dev/null +++ b/licenses/data/org_modernc_mathutil/mersenne/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The mersenne Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the names of the authors nor the names of the +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/org_modernc_memory/LICENSE b/licenses/data/org_modernc_memory/LICENSE new file mode 100644 index 000000000..967339afc --- /dev/null +++ b/licenses/data/org_modernc_memory/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2017 The Memory Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the names of the authors nor the names of the +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/org_modernc_memory/LICENSE-GO b/licenses/data/org_modernc_memory/LICENSE-GO new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/licenses/data/org_modernc_memory/LICENSE-GO @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/org_modernc_memory/LICENSE-MMAP-GO b/licenses/data/org_modernc_memory/LICENSE-MMAP-GO new file mode 100644 index 000000000..8f05f338a --- /dev/null +++ b/licenses/data/org_modernc_memory/LICENSE-MMAP-GO @@ -0,0 +1,25 @@ +Copyright (c) 2011, Evan Shaw +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/licenses/data/org_modernc_sqlite/LICENSE b/licenses/data/org_modernc_sqlite/LICENSE new file mode 100644 index 000000000..867b0f379 --- /dev/null +++ b/licenses/data/org_modernc_sqlite/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2017 The Sqlite Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/org_modernc_sqlite/SQLITE-LICENSE b/licenses/data/org_modernc_sqlite/SQLITE-LICENSE new file mode 100644 index 000000000..cc4c78e3d --- /dev/null +++ b/licenses/data/org_modernc_sqlite/SQLITE-LICENSE @@ -0,0 +1,25 @@ +SQLite Is Public Domain + +All of the code and documentation in SQLite has been dedicated to the public +domain by the authors. All code authors, and representatives of the companies +they work for, have signed affidavits dedicating their contributions to the +public domain and originals of those signed affidavits are stored in a firesafe +at the main offices of Hwaci. Anyone is free to copy, modify, publish, use, +compile, sell, or distribute the original SQLite code, either in source code +form or as a compiled binary, for any purpose, commercial or non-commercial, +and by any means. + +The previous paragraph applies to the deliverable code and documentation in +SQLite - those parts of the SQLite library that you actually bundle and ship +with a larger application. Some scripts used as part of the build process (for +example the "configure" scripts generated by autoconf) might fall under other +open-source licenses. Nothing from these build scripts ever reaches the final +deliverable SQLite library, however, and so the licenses associated with those +scripts should not be a factor in assessing your rights to copy and use the +SQLite library. + +All of the deliverable code in SQLite has been written from scratch. No code +has been taken from other projects or from the open internet. Every line of +code can be traced back to its original author, and all of those authors have +public domain dedications on file. So the SQLite code base is clean and is +uncontaminated with licensed code from other projects. diff --git a/nogo.json b/nogo.json index 2724a13b9..8e6ff5d7f 100644 --- a/nogo.json +++ b/nogo.json @@ -2,7 +2,8 @@ "assign": { "exclude_files": { "gazelle/walk/walk.go": "", - "com_github_deepmap_oapi_codegen/pkg/codegen/": "" + "com_github_deepmap_oapi_codegen/pkg/codegen/": "", + "/org_modernc_sqlite": "" } }, "composites": { @@ -73,7 +74,9 @@ "/com_github_magiconair_properties": "", "/com_github_ghodss_yaml/": "", "/com_github_lestrrat_go_iter/mapiter/": "", - "/com_github_lestrrat_go_iter/arrayiter/": "" + "/com_github_lestrrat_go_iter/arrayiter/": "", + "/org_modernc_libc": "", + "/org_modernc_sqlite": "" } }, "unsafeptr": { @@ -105,7 +108,9 @@ }, "stdmethods": { "exclude_files": { - "/com_github_uber_jaeger_client_go": "" + "/com_github_uber_jaeger_client_go": "", + "/org_modernc_sqlite": "", + "/org_modernc_mathutil": "" } }, "structtag": { diff --git a/private/storage/beacon/sqlite/BUILD.bazel b/private/storage/beacon/sqlite/BUILD.bazel index 1e265e09c..fb536c303 100644 --- a/private/storage/beacon/sqlite/BUILD.bazel +++ b/private/storage/beacon/sqlite/BUILD.bazel @@ -16,7 +16,6 @@ go_library( "//pkg/private/util:go_default_library", "//private/storage/beacon:go_default_library", "//private/storage/db:go_default_library", - "@com_github_mattn_go_sqlite3//:go_default_library", ], ) diff --git a/private/storage/beacon/sqlite/db.go b/private/storage/beacon/sqlite/db.go index 4c76036f2..f6b2de6ad 100644 --- a/private/storage/beacon/sqlite/db.go +++ b/private/storage/beacon/sqlite/db.go @@ -22,8 +22,6 @@ import ( "sync" "time" - _ "github.com/mattn/go-sqlite3" - "github.com/scionproto/scion/control/beacon" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/common" diff --git a/private/storage/db/BUILD.bazel b/private/storage/db/BUILD.bazel index fa5d8594a..9ed6145d9 100644 --- a/private/storage/db/BUILD.bazel +++ b/private/storage/db/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "metrics.go", "sqler.go", "sqlite.go", + "sqlite_modernc.go", ], importpath = "github.com/scionproto/scion/private/storage/db", visibility = ["//visibility:public"], @@ -16,6 +17,7 @@ go_library( "//pkg/private/common:go_default_library", "//pkg/private/prom:go_default_library", "//pkg/private/serrors:go_default_library", + "@org_modernc_sqlite//:go_default_library", ], ) diff --git a/private/storage/db/sqlite.go b/private/storage/db/sqlite.go index 15e04f6c4..5e0dde3f5 100644 --- a/private/storage/db/sqlite.go +++ b/private/storage/db/sqlite.go @@ -22,6 +22,8 @@ import ( "github.com/scionproto/scion/pkg/private/serrors" ) +const _ = buildtag_guard_either_sqlite_mattn_or_sqlite_modernc + // NewSqlite returns a new SQLite backend opening a database at the given path. If // no database exists a new database is be created. If the schema version of the // stored database is different from schemaVersion, an error is returned. @@ -67,14 +69,12 @@ func open(path string) (*sql.DB, error) { return nil, serrors.WrapStr("invalid connection path", err, "path", path) } - q := u.Query() // Add foreign_key parameter to path to enable foreign key support. - q.Set("_foreign_keys", "1") - // prevent weird errors. (see https://stackoverflow.com/a/35805826) - q.Set("_journal_mode", "WAL") + q := u.Query() + addPragmas(q) u.RawQuery = q.Encode() path = u.String() - db, err := sql.Open("sqlite3", path) + db, err := sql.Open(driverName(), path) if err != nil { return nil, serrors.WrapStr("Couldn't open SQLite database", err, "path", path) } diff --git a/private/storage/db/sqlite_mattn.go b/private/storage/db/sqlite_mattn.go new file mode 100644 index 000000000..805a64609 --- /dev/null +++ b/private/storage/db/sqlite_mattn.go @@ -0,0 +1,41 @@ +// Copyright 2023 SCION Association +// +// 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. + +//go:build sqlite_mattn + +package db + +import ( + "net/url" + + _ "github.com/mattn/go-sqlite3" +) + +const buildtag_guard_either_sqlite_mattn_or_sqlite_modernc = "must choose an sqlite " + + "implementation to build, by defining exactly one of the gotags " + + "'sqlite_modernc' or 'sqlite_mattn'" + +// addPragmas() modifies given URL query so it can be used to make the correct uri +// connection path for this sqlite implementation. The modifications turn on +// foreign keys and WAL journal mode for every SQL query. +func addPragmas(q url.Values) { + // Add foreign_key parameter to path to enable foreign key support. + q.Set("_foreign_keys", "1") + // prevent weird errors. (see https://stackoverflow.com/a/35805826) + q.Set("_journal_mode", "WAL") +} + +func driverName() string { + return "sqlite3" +} diff --git a/private/storage/db/sqlite_modernc.go b/private/storage/db/sqlite_modernc.go new file mode 100644 index 000000000..951985b23 --- /dev/null +++ b/private/storage/db/sqlite_modernc.go @@ -0,0 +1,48 @@ +// Copyright 2023 SCION Association +// +// 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. + +//go:build sqlite_modernc || !sqlite_mattn + +// Note that above go:build expression makes modernc the default by matching +// the absence of sqlite_mattn. Should there be more alternatives, please +// update that expression to match their absence too. +// Also note that this default is overridden by a build configuration +// in .bazelrc, so this is only useful when building with "go build" and +// may not match the bazel build configuration. + +package db + +import ( + "net/url" + + _ "modernc.org/sqlite" +) + +const buildtag_guard_either_sqlite_mattn_or_sqlite_modernc = "must choose an sqlite " + + "implementation to build, by defining exactly one of the gotags " + + "'sqlite_modernc' or 'sqlite_mattn'" + +// addPragmas() modifies given URL query so it can be used to make the correct uri +// connection path for this sqlite implementation. The modifications turn on +// foreign keys and WAL journal mode for every SQL query. +func addPragmas(q url.Values) { + // Add foreign_key parameter to path to enable foreign key support. + q.Add("_pragma", "foreign_keys=1") + // prevent weird errors. (see https://stackoverflow.com/a/35805826) + q.Add("_pragma", "journal_mode=WAL") +} + +func driverName() string { + return "sqlite" +} diff --git a/private/storage/drkey/level1/sqlite/BUILD.bazel b/private/storage/drkey/level1/sqlite/BUILD.bazel index fb58e5424..162d041ab 100644 --- a/private/storage/drkey/level1/sqlite/BUILD.bazel +++ b/private/storage/drkey/level1/sqlite/BUILD.bazel @@ -9,7 +9,6 @@ go_library( "//pkg/drkey:go_default_library", "//pkg/private/util:go_default_library", "//private/storage/db:go_default_library", - "@com_github_mattn_go_sqlite3//:go_default_library", ], ) diff --git a/private/storage/drkey/level1/sqlite/db.go b/private/storage/drkey/level1/sqlite/db.go index 2b18074b2..7b6a3a239 100644 --- a/private/storage/drkey/level1/sqlite/db.go +++ b/private/storage/drkey/level1/sqlite/db.go @@ -20,8 +20,6 @@ import ( "sync" "time" - _ "github.com/mattn/go-sqlite3" - "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/private/storage/db" diff --git a/private/storage/drkey/level2/sqlite/BUILD.bazel b/private/storage/drkey/level2/sqlite/BUILD.bazel index ccbc061ef..58c2e9cfb 100644 --- a/private/storage/drkey/level2/sqlite/BUILD.bazel +++ b/private/storage/drkey/level2/sqlite/BUILD.bazel @@ -9,7 +9,6 @@ go_library( "//pkg/drkey:go_default_library", "//pkg/private/util:go_default_library", "//private/storage/db:go_default_library", - "@com_github_mattn_go_sqlite3//:go_default_library", ], ) diff --git a/private/storage/drkey/level2/sqlite/db.go b/private/storage/drkey/level2/sqlite/db.go index 6570427d1..f0e212c0f 100644 --- a/private/storage/drkey/level2/sqlite/db.go +++ b/private/storage/drkey/level2/sqlite/db.go @@ -20,8 +20,6 @@ import ( "sync" "time" - _ "github.com/mattn/go-sqlite3" - "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/private/storage/db" diff --git a/private/storage/drkey/secret/sqlite/BUILD.bazel b/private/storage/drkey/secret/sqlite/BUILD.bazel index f4736d09d..40191a2bf 100644 --- a/private/storage/drkey/secret/sqlite/BUILD.bazel +++ b/private/storage/drkey/secret/sqlite/BUILD.bazel @@ -9,7 +9,6 @@ go_library( "//pkg/drkey:go_default_library", "//pkg/private/util:go_default_library", "//private/storage/db:go_default_library", - "@com_github_mattn_go_sqlite3//:go_default_library", ], ) diff --git a/private/storage/drkey/secret/sqlite/db.go b/private/storage/drkey/secret/sqlite/db.go index 818bf8eb1..6511c1be9 100644 --- a/private/storage/drkey/secret/sqlite/db.go +++ b/private/storage/drkey/secret/sqlite/db.go @@ -20,8 +20,6 @@ import ( "sync" "time" - _ "github.com/mattn/go-sqlite3" - "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/private/storage/db" diff --git a/private/storage/path/sqlite/BUILD.bazel b/private/storage/path/sqlite/BUILD.bazel index 480c055e8..2bf89eda0 100644 --- a/private/storage/path/sqlite/BUILD.bazel +++ b/private/storage/path/sqlite/BUILD.bazel @@ -17,7 +17,6 @@ go_library( "//private/storage/db:go_default_library", "//private/storage/path:go_default_library", "//private/storage/utils:go_default_library", - "@com_github_mattn_go_sqlite3//:go_default_library", ], ) diff --git a/private/storage/path/sqlite/sqlite.go b/private/storage/path/sqlite/sqlite.go index 78961c810..a11748d27 100644 --- a/private/storage/path/sqlite/sqlite.go +++ b/private/storage/path/sqlite/sqlite.go @@ -26,8 +26,6 @@ import ( "sync" "time" - _ "github.com/mattn/go-sqlite3" - "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/serrors" seg "github.com/scionproto/scion/pkg/segment" diff --git a/private/storage/trust/sqlite/BUILD.bazel b/private/storage/trust/sqlite/BUILD.bazel index 65f66ca7b..688b9292d 100644 --- a/private/storage/trust/sqlite/BUILD.bazel +++ b/private/storage/trust/sqlite/BUILD.bazel @@ -14,7 +14,6 @@ go_library( "//private/storage/db:go_default_library", "//private/storage/trust:go_default_library", "//private/trust:go_default_library", - "@com_github_mattn_go_sqlite3//:go_default_library", ], ) diff --git a/private/storage/trust/sqlite/db.go b/private/storage/trust/sqlite/db.go index 388469fb6..aa7f49aeb 100644 --- a/private/storage/trust/sqlite/db.go +++ b/private/storage/trust/sqlite/db.go @@ -23,8 +23,6 @@ import ( "strings" "sync" - _ "github.com/mattn/go-sqlite3" - "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/scrypto/cppki" "github.com/scionproto/scion/private/storage/db" diff --git a/tools/dc b/tools/dc index 9aad5d98e..2b21ec3f3 100755 --- a/tools/dc +++ b/tools/dc @@ -83,7 +83,7 @@ dc() { local project="$1" local dc_file="gen/$1-dc.yml" shift - COMPOSE_FILE="$dc_file" docker-compose -p "$project" --no-ansi "$@" + COMPOSE_FILE="$dc_file" docker-compose -p "$project" --ansi never "$@" } cmd_collect_logs() { diff --git a/tools/env/rhel/deps b/tools/env/rhel/deps index 007bc9153..533f4e69e 100755 --- a/tools/env/rhel/deps +++ b/tools/env/rhel/deps @@ -3,4 +3,5 @@ set -e sudo yum groupinstall -y "Development Tools" -sudo yum install -y jq +BASE=$(dirname "$0") +xargs -a "$BASE/pkgs.txt" sudo yum install -y diff --git a/tools/env/rhel/pkgs.txt b/tools/env/rhel/pkgs.txt new file mode 100644 index 000000000..737fe222c --- /dev/null +++ b/tools/env/rhel/pkgs.txt @@ -0,0 +1,10 @@ +bridge-utils +moreutils +gcc +g++ +python3-pip +python3-setuptools +python3-wheel +jq +sqlite3 +openssl diff --git a/tools/install_deps b/tools/install_deps index 6ac5bf0ce..b43f43d75 100755 --- a/tools/install_deps +++ b/tools/install_deps @@ -3,9 +3,9 @@ set -e BASE=$(dirname "$0") -"$BASE/env/pip3/deps" if which apt-get >& /dev/null; then "$BASE/env/debian/deps" elif which yum >& /dev/null; then "$BASE/env/rhel/deps" fi +"$BASE/env/pip3/deps" diff --git a/tools/update_testdata.sh b/tools/update_testdata.sh index 71372413d..1d4874a31 100755 --- a/tools/update_testdata.sh +++ b/tools/update_testdata.sh @@ -10,5 +10,7 @@ folders=$(grep \ --exclude-dir=bazel-\* \ "xtest.UpdateGoldenFiles()" . | xargs dirname | sort | uniq ) -echo $folders -update | xargs go test -echo $folders -count=1 | xargs go test +GO_BUILD_TAGS_ARG=$(bazel build --ui_event_filters=-stdout,-stderr --announce_rc --noshow_progress :dummy_setting 2>&1 | grep "'build' options" | sed -n "s/^.*--define gotags=\(\S*\).*/-tags \1/p") + +echo $folders -update | xargs go test ${GO_BUILD_TAGS_ARG} +echo $folders -count=1 | xargs go test ${GO_BUILD_TAGS_ARG} From d9acea4b6c3bb6463af4a22a48e7c44237a26685 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Mon, 21 Aug 2023 10:23:26 +0200 Subject: [PATCH 047/255] dispatcher: support auto-assigned port for SVC registrations (#4381) fixes #4379 --- dispatcher/internal/registration/table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dispatcher/internal/registration/table.go b/dispatcher/internal/registration/table.go index 278cbc892..a0244c0de 100644 --- a/dispatcher/internal/registration/table.go +++ b/dispatcher/internal/registration/table.go @@ -60,7 +60,7 @@ func (t *Table) Register(public *net.UDPAddr, bind net.IP, svc addr.SVC, if bind == nil { bind = public.IP } - svcRef, err := t.insertSVCIfRequested(svc, bind, public.Port, value) + svcRef, err := t.insertSVCIfRequested(svc, bind, address.Port, value) if err != nil { t.udpPortTable.Remove(public) return nil, err From 8d95532d9a53d1284b777aba46d8ceb0eeb0891f Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Mon, 28 Aug 2023 18:33:39 +0200 Subject: [PATCH 048/255] scion.sh: do a more complete shutdown by default (#4382) --- scion.sh | 13 +++---------- tools/dc | 2 +- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/scion.sh b/scion.sh index 371f41027..c437e3212 100755 --- a/scion.sh +++ b/scion.sh @@ -11,14 +11,7 @@ cmd_bazel_remote() { cmd_topo_clean() { set -e - if is_docker_be; then - echo "Shutting down dockerized topology..." - ./tools/quiet ./tools/dc down || true - else - ./tools/quiet tools/supervisor.sh shutdown - run_teardown - fi - stop_jaeger + cmd_stop || true rm -rf traces/* mkdir -p logs traces gen gen-cache gen-certs find gen gen-cache gen-certs -mindepth 1 -maxdepth 1 -exec rm -r {} + @@ -109,9 +102,9 @@ run_teardown() { cmd_stop() { echo "Terminating this run of the SCION infrastructure" if is_docker_be; then - ./tools/quiet ./tools/dc stop 'scion*' + ./tools/quiet ./tools/dc down else - ./tools/quiet tools/supervisor.sh stop all + ./tools/quiet tools/supervisor.sh shutdown run_teardown fi stop_jaeger diff --git a/tools/dc b/tools/dc index 2b21ec3f3..7901082a3 100755 --- a/tools/dc +++ b/tools/dc @@ -59,7 +59,7 @@ cmd_stop() { } cmd_down() { - cmd_scion down -v + cmd_scion down -v --remove-orphans } cmd_run() { From 9bdd29ccfe7994e50a689d4d0fe9f7b8c43de3ca Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Tue, 29 Aug 2023 09:45:45 +0200 Subject: [PATCH 049/255] hidden_paths: enable registration of hiddenpaths both locally and remotely. Fixes #4364 There were a number of issues: * Because the normal case is that the registry is remote, the registerer makes no attempt at using the intraAS network to reach the registry (and the registry isn't listening on TCP). However, quic/scion path resolution to an AS-local host was broken: the resulting paths are expected to be complete paths with Metadata, but intraAS paths were meta-data-less paths, resulting in nill-ptr dereference. * By default the control service port (shared with the hidden_segment registry) was a dynamic port. The discovery service cannot only knows of statically configured port (configured in the topo file). So the only way to make the hidden_segments service discoverable is to give the control service a static port. While possible, this would result in a confusing and conter-intuitive configuration: * the control_service quic address would be configured by the cs yaml file and be different from what appears in the topo file for the CS but identical to the hidden_segment service address. * the CS address in the topo file was acually the TCP address and could never be mirrored by the quic address (because that quic address was occupied by the service resolver). * the address of the hidden_segments registry in the topo file would be different from that of the CS, eventhough they share the same port. * This was all invisible to the integration test which was skillfully predicting the dynamic port and configuring the discovery service for it. To correct these infelicities: * Give the Svc resolver a dynamic port * By default, give to the CS and the hidden_segment registry the quic address that has the same IP and port as the control service's TCP address. * Produce complete Path objects to represent intraAS paths. In passing: * A handful of AssertEqual() had arguments in the wrong order. * In one case we were constructing a full SVC address with a nil path instead of an empty path. --- acceptance/common/scion.py | 37 +++++++++++++++++- acceptance/hidden_paths/test.py | 19 +++------- control/cmd/control/main.go | 9 ++++- control/hiddenpaths.go | 3 +- control/tasks.go | 5 +++ pkg/experimental/hiddenpath/BUILD.bazel | 1 + pkg/experimental/hiddenpath/discovery.go | 16 +++++--- pkg/snet/path.go | 4 -- pkg/snet/router.go | 13 ------- private/app/appnet/BUILD.bazel | 2 + private/app/appnet/addr.go | 1 + private/app/appnet/addr_test.go | 29 +++++++------- private/app/appnet/infraenv.go | 17 +++++++-- private/app/appnet/intra_as.go | 48 ++++++++++++++++++++++++ 14 files changed, 148 insertions(+), 56 deletions(-) create mode 100644 private/app/appnet/intra_as.go diff --git a/acceptance/common/scion.py b/acceptance/common/scion.py index 9ad00ae03..c330fb20c 100644 --- a/acceptance/common/scion.py +++ b/acceptance/common/scion.py @@ -14,7 +14,7 @@ import logging import json -from typing import Any, Dict, List, MutableMapping +from typing import Any, Dict, List, MutableMapping, Mapping import toml import yaml @@ -69,6 +69,29 @@ def update_json(change_dict: Dict[str, Any], files: LocalPath): json.dump(t, f, indent=2) +def load_from_json(key: str, files: LocalPath) -> Any: + """ Reads the value associated with the given key from the given json files. + + The first value found is returned. If not found, None is returned. + + Args: + key: dot separated path of the JSON key. + files: names of file or files to read. + + Returns: + The value. None if the path doesn't exist in the dictionary tree. + + Raises: + IOError / FileNotFoundError: File path is not valid + """ + for file in files: + with open(file, "r") as f: + t = json.load(f) + v = val_at_path(t, key) + if v is not None: + return v + + class ASList: """ ASList is a list of AS separated by core and non-core ASes. It can be loaded @@ -117,6 +140,18 @@ def path_to_dict(path: str, val: Any) -> Dict: return d +def val_at_path(d: Mapping[str, Any], path: str) -> Any: + """ + Walks nested dictionaries by following the given path and returns the value + associated with the leaf key. + """ + v = d + for k in path.split('.'): + v = v.get(k, None) + if not isinstance(v, Mapping): + return v + + def merge_dict(change_dict: Dict[str, Any], orig_dict: MutableMapping[str, Any]): """ Merge changes into the original dictionary. Leaf values in the change dict diff --git a/acceptance/hidden_paths/test.py b/acceptance/hidden_paths/test.py index c3144c9e4..3a9f1af7f 100755 --- a/acceptance/hidden_paths/test.py +++ b/acceptance/hidden_paths/test.py @@ -61,16 +61,6 @@ def setup_prepare(self): "4": "172.20.0.65", "5": "172.20.0.73", } - # XXX(lukedirtwalker): The ports below are the dynamic QUIC server - # ports. Thanks to the docker setup they are setup consistently so we - # can use them. Optimally we would define a static server port inside - # the CS and use that one instead. - control_addresses = { - "2": "172.20.0.51:32768", - "3": "172.20.0.59:32768", - "4": "172.20.0.67:32768", - "5": "172.20.0.75:32768", - } # Each AS participating in hidden paths has their own hidden paths configuration file. hp_configs = { "2": "hp_groups_as2_as5.yml", @@ -98,13 +88,16 @@ def setup_prepare(self): # even though some don't need the registration service. as_dir_path = self.artifacts / "gen" / ("ASff00_0_%s" % as_number) + # The hidden_segment services are behind the same server as the control_service. + topology_file = as_dir_path / "topology.json" + control_service_addr = scion.load_from_json( + 'control_service.%s.addr' % control_id, [topology_file]) topology_update = { "hidden_segment_lookup_service.%s.addr" % control_id: - control_addresses[as_number], + control_service_addr, "hidden_segment_registration_service.%s.addr" % control_id: - control_addresses[as_number], + control_service_addr, } - topology_file = as_dir_path / "topology.json" scion.update_json(topology_update, [topology_file]) def setup_start(self): diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index d481cd607..d5de9e08f 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -200,11 +200,17 @@ func realMain(ctx context.Context) error { return err } + // FIXME: readability would be improved if we could be consistent with address + // representations in NetworkConfig (string or cooked, chose one). nc := infraenv.NetworkConfig{ - IA: topo.IA(), + IA: topo.IA(), + // Public: (Historical name) The TCP/IP:port address for the control service. Public: topo.ControlServiceAddress(globalCfg.General.ID), ReconnectToDispatcher: globalCfg.General.ReconnectToDispatcher, QUIC: infraenv.QUIC{ + // Address: the QUIC/SCION address of this service. If not + // configured, QUICStack() uses the same IP and port as + // for the public address. Address: globalCfg.QUIC.Address, TLSVerifier: trust.NewTLSCryptoVerifier(trustDB), GetCertificate: cs.NewTLSCertificateLoader( @@ -221,6 +227,7 @@ func realMain(ctx context.Context) error { }, SCIONNetworkMetrics: metrics.SCIONNetworkMetrics, SCIONPacketConnMetrics: metrics.SCIONPacketConnMetrics, + MTU: topo.MTU(), } quicStack, err := nc.QUICStack() if err != nil { diff --git a/control/hiddenpaths.go b/control/hiddenpaths.go index f0036c1f1..299d26587 100644 --- a/control/hiddenpaths.go +++ b/control/hiddenpaths.go @@ -84,7 +84,8 @@ func (c HiddenPathConfigurator) Setup(location string) (*HiddenPathRegistrationC &hpgrpc.AuthoritativeSegmentServer{ Lookup: c.localAuthServer(groups), Verifier: c.Verifier, - }) + }, + ) hspb.RegisterHiddenSegmentRegistrationServiceServer(c.InterASQUICServer, &hpgrpc.RegistrationServer{ Registry: hiddenpath.RegistryServer{ diff --git a/control/tasks.go b/control/tasks.go index 4b8a8ab75..fedae5e90 100644 --- a/control/tasks.go +++ b/control/tasks.go @@ -196,6 +196,11 @@ func (t *TasksConfig) segmentWriter(segType seg.Type, Writer: writer, Tick: beaconing.NewTick(t.RegistrationInterval), } + // The period of the task is short because we want to retry quickly + // if we fail fast. So during one interval we'll make as many attempts + // as we can until we succeed. After succeeding, the task does nothing + // until the end of the interval. The interval itself is used as a + // timeout. If we fail slow we give up at the end of the cycle. return periodic.Start(r, 500*time.Millisecond, t.RegistrationInterval) } diff --git a/pkg/experimental/hiddenpath/BUILD.bazel b/pkg/experimental/hiddenpath/BUILD.bazel index ee33cdb96..3962a4665 100644 --- a/pkg/experimental/hiddenpath/BUILD.bazel +++ b/pkg/experimental/hiddenpath/BUILD.bazel @@ -25,6 +25,7 @@ go_library( "//pkg/private/serrors:go_default_library", "//pkg/segment:go_default_library", "//pkg/snet:go_default_library", + "//pkg/snet/path:go_default_library", "//private/config:go_default_library", "//private/pathdb:go_default_library", "//private/pathdb/query:go_default_library", diff --git a/pkg/experimental/hiddenpath/discovery.go b/pkg/experimental/hiddenpath/discovery.go index 8418debb9..f336a152c 100644 --- a/pkg/experimental/hiddenpath/discovery.go +++ b/pkg/experimental/hiddenpath/discovery.go @@ -21,6 +21,7 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/snet" + "github.com/scionproto/scion/pkg/snet/path" ) // Servers is a list of discovered remote hidden segment server. @@ -80,19 +81,22 @@ func (r LookupResolver) Resolve(ctx context.Context, ia addr.IA) (net.Addr, erro func resolve(ctx context.Context, ia addr.IA, discoverer Discoverer, router snet.Router, extractAddr func(Servers) (*net.UDPAddr, error)) (net.Addr, error) { - path, err := router.Route(ctx, ia) + p, err := router.Route(ctx, ia) if err != nil { return nil, serrors.WrapStr("looking up path", err) } - if path == nil { + if p == nil { return nil, serrors.WrapStr("no path found to remote", err) } dsAddr := &snet.SVCAddr{ IA: ia, - NextHop: path.UnderlayNextHop(), - Path: path.Dataplane(), + NextHop: p.UnderlayNextHop(), + Path: p.Dataplane(), SVC: addr.SvcDS, } + if dsAddr.Path == nil { + dsAddr.Path = path.Empty{} + } hps, err := discoverer.Discover(ctx, dsAddr) if err != nil { return nil, serrors.WrapStr("discovering hidden path server", err) @@ -104,7 +108,7 @@ func resolve(ctx context.Context, ia addr.IA, discoverer Discoverer, router snet return &snet.UDPAddr{ IA: ia, Host: a, - NextHop: path.UnderlayNextHop(), - Path: path.Dataplane(), + NextHop: dsAddr.NextHop, + Path: dsAddr.Path, }, nil } diff --git a/pkg/snet/path.go b/pkg/snet/path.go index 8fa12fc03..1a19ad576 100644 --- a/pkg/snet/path.go +++ b/pkg/snet/path.go @@ -249,10 +249,6 @@ func (p *partialPath) Dataplane() DataplanePath { return p.dataplane } -func (p *partialPath) Interfaces() []PathInterface { - return nil -} - func (p *partialPath) Source() addr.IA { return p.source } diff --git a/pkg/snet/router.go b/pkg/snet/router.go index f763a529b..a11f78c1a 100644 --- a/pkg/snet/router.go +++ b/pkg/snet/router.go @@ -55,16 +55,3 @@ func (r *BaseRouter) Route(ctx context.Context, dst addr.IA) (Path, error) { func (r *BaseRouter) AllRoutes(ctx context.Context, dst addr.IA) ([]Path, error) { return r.Querier.Query(ctx, dst) } - -// IntraASPathQuerier implements the PathQuerier interface. It will only provide -// AS internal paths, i.e., empty paths with only the IA as destination. This -// should only be used in places where you know that you only need to -// communicate inside the AS. -type IntraASPathQuerier struct { - IA addr.IA -} - -// Query implements PathQuerier. -func (q IntraASPathQuerier) Query(_ context.Context, _ addr.IA) ([]Path, error) { - return []Path{&partialPath{source: q.IA, destination: q.IA}}, nil -} diff --git a/private/app/appnet/BUILD.bazel b/private/app/appnet/BUILD.bazel index a65d75e38..68f765018 100644 --- a/private/app/appnet/BUILD.bazel +++ b/private/app/appnet/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "addr.go", "infraenv.go", + "intra_as.go", ], importpath = "github.com/scionproto/scion/private/app/appnet", visibility = ["//visibility:public"], @@ -13,6 +14,7 @@ go_library( "//pkg/daemon:go_default_library", "//pkg/log:go_default_library", "//pkg/private/serrors:go_default_library", + "//pkg/slayers/path:go_default_library", "//pkg/snet:go_default_library", "//pkg/snet/path:go_default_library", "//pkg/snet/squic:go_default_library", diff --git a/private/app/appnet/addr.go b/private/app/appnet/addr.go index 4bbd73303..2d5514c40 100644 --- a/private/app/appnet/addr.go +++ b/private/app/appnet/addr.go @@ -161,6 +161,7 @@ func (r AddressRewriter) buildFullAddress(ctx context.Context, return nil, serrors.WrapStr("Unable to resolve underlay", err) } ret.NextHop = ov + ret.Path = path.Empty{} } return ret, nil diff --git a/private/app/appnet/addr_test.go b/private/app/appnet/addr_test.go index 27bba692c..dd6a009d3 100644 --- a/private/app/appnet/addr_test.go +++ b/private/app/appnet/addr_test.go @@ -80,8 +80,8 @@ func TestRedirectQUIC(t *testing.T) { a, r, err := aw.RedirectToQUIC(context.Background(), tc.input) tc.assertErr(t, err) - assert.Equal(t, a, tc.wantAddr) - assert.Equal(t, r, tc.wantRedirect) + assert.Equal(t, tc.wantAddr, a) + assert.Equal(t, tc.wantRedirect, r) }) } @@ -100,7 +100,6 @@ func TestRedirectQUIC(t *testing.T) { path.EXPECT().Metadata().Return(&snet.PathMetadata{ Interfaces: make([]snet.PathInterface, 1), // just non-empty }) - aw := infraenv.AddressRewriter{ Router: router, Resolver: resolver, @@ -137,7 +136,6 @@ func TestRedirectQUIC(t *testing.T) { path.EXPECT().Metadata().Return(&snet.PathMetadata{ Interfaces: make([]snet.PathInterface, 1), // just non-empty }) - aw := infraenv.AddressRewriter{ Router: router, Resolver: resolver, @@ -182,7 +180,7 @@ func TestRedirectQUIC(t *testing.T) { want := &snet.SVCAddr{ SVC: addr.SvcCS, NextHop: &net.UDPAddr{IP: net.ParseIP("10.1.1.1")}, - Path: snetpath.SCION{}, + Path: snetpath.Empty{}, } a, r, err := aw.RedirectToQUIC(context.Background(), input) assert.NoError(t, err) @@ -225,7 +223,7 @@ func TestBuildFullAddress(t *testing.T) { SVC: addr.SvcCS, } a, err := aw.BuildFullAddress(context.Background(), input) - assert.Equal(t, a, input) + assert.Equal(t, input, a) assert.NoError(t, err) }) @@ -255,7 +253,7 @@ func TestBuildFullAddress(t *testing.T) { NextHop: &net.UDPAddr{}, SVC: addr.SvcCS, } - assert.Equal(t, a, want) + assert.Equal(t, want, a) assert.NoError(t, err) }) @@ -285,8 +283,13 @@ func TestBuildFullAddress(t *testing.T) { input := &snet.SVCAddr{IA: localIA, SVC: addr.SvcCS, Path: snetpath.Empty{}} a, err := aw.BuildFullAddress(context.Background(), input) - want := &snet.SVCAddr{IA: localIA, NextHop: underlayAddr, SVC: addr.SvcCS} - assert.Equal(t, a, want) + want := &snet.SVCAddr{ + IA: localIA, + NextHop: underlayAddr, + SVC: addr.SvcCS, + Path: snetpath.Empty{}, + } + assert.Equal(t, want, a) assert.NoError(t, err) }) @@ -388,9 +391,9 @@ func TestResolve(t *testing.T) { } initResolver(resolver, tc.ResolverSetup) p, a, redirect, err := aw.ResolveSVC(context.Background(), path, tc.input) - assert.Equal(t, p, tc.wantPath) - assert.Equal(t, a.String(), tc.want.String()) - assert.Equal(t, redirect, tc.wantQUICRedirect) + assert.Equal(t, tc.wantPath, p) + assert.Equal(t, tc.want.String(), a.String()) + assert.Equal(t, tc.wantQUICRedirect, redirect) tc.assertErr(t, err) }) } @@ -448,7 +451,7 @@ func TestParseReply(t *testing.T) { if err != nil { return } - assert.Equal(t, a.String(), tc.want.String()) + assert.Equal(t, tc.want.String(), a.String()) }) } } diff --git a/private/app/appnet/infraenv.go b/private/app/appnet/infraenv.go index 595cd1cc0..c9fdd7646 100644 --- a/private/app/appnet/infraenv.go +++ b/private/app/appnet/infraenv.go @@ -83,6 +83,8 @@ type NetworkConfig struct { SCIONNetworkMetrics snet.SCIONNetworkMetrics // Metrics injected into DefaultPacketDispatcherService. SCIONPacketConnMetrics snet.SCIONPacketConnMetrics + // MTU of the local AS + MTU uint16 } // QUICStack contains everything to run a QUIC based RPC stack. @@ -103,8 +105,9 @@ func (nc *NetworkConfig) TCPStack() (net.Listener, error) { func (nc *NetworkConfig) QUICStack() (*QUICStack, error) { if nc.QUIC.Address == "" { - nc.QUIC.Address = net.JoinHostPort(nc.Public.IP.String(), "0") + nc.QUIC.Address = nc.Public.String() } + client, server, err := nc.initQUICSockets() if err != nil { return nil, err @@ -221,7 +224,7 @@ func (nc *NetworkConfig) AddressRewriter( } } return &AddressRewriter{ - Router: &snet.BaseRouter{Querier: snet.IntraASPathQuerier{IA: nc.IA}}, + Router: &snet.BaseRouter{Querier: IntraASPathQuerier{IA: nc.IA, MTU: nc.MTU}}, SVCRouter: nc.SVCResolver, Resolver: &svc.Resolver{ LocalIA: nc.IA, @@ -266,9 +269,15 @@ func (nc *NetworkConfig) initSvcRedirect(quicAddress string) (func(), error) { Dispatcher: packetDispatcher, Metrics: nc.SCIONNetworkMetrics, } - conn, err := network.Listen(context.Background(), "udp", nc.Public, addr.SvcWildcard) + + // The service resolution address gets a dynamic port. In reality, neither the + // address nor the port are needed to address the resolver, but the dispatcher still + // requires them and checks unicity. At least a dynamic port is allowed. + srAddr := &net.UDPAddr{IP: nc.Public.IP, Port: 0} + conn, err := network.Listen(context.Background(), "udp", srAddr, addr.SvcWildcard) if err != nil { - return nil, serrors.WrapStr("listening on SCION", err, "addr", nc.Public) + log.Info("Listen failed", "err", err) + return nil, serrors.WrapStr("listening on SCION", err, "addr", srAddr) } ctx, cancel := context.WithCancel(context.Background()) diff --git a/private/app/appnet/intra_as.go b/private/app/appnet/intra_as.go new file mode 100644 index 000000000..6735dce53 --- /dev/null +++ b/private/app/appnet/intra_as.go @@ -0,0 +1,48 @@ +// Copyright 2020 ETH Zurich +// +// 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 appnet + +import ( + "context" + "time" + + "github.com/scionproto/scion/pkg/addr" + rawpath "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/pkg/snet" + "github.com/scionproto/scion/pkg/snet/path" +) + +// IntraASPathQuerier implements the PathQuerier interface. It will only provide +// AS-internal paths, i.e., zero-hops paths with only the IA as destination. This +// should only be used in places where you know that you only need to +// communicate inside the AS. The type of Path returned is a complete +// implementation with proper metadata. +type IntraASPathQuerier struct { + IA addr.IA + MTU uint16 +} + +// Query implements PathQuerier. +func (q IntraASPathQuerier) Query(_ context.Context, _ addr.IA) ([]snet.Path, error) { + return []snet.Path{path.Path{ + Src: q.IA, + Dst: q.IA, + DataplanePath: path.Empty{}, + Meta: snet.PathMetadata{ + MTU: q.MTU, + Expiry: time.Now().Add(rawpath.MaxTTL * time.Second), + }, + }}, nil +} From 5e04af0208ab87451671036b64087e79a4a488d6 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Thu, 7 Sep 2023 13:25:04 +0200 Subject: [PATCH 050/255] build: update quic-go version (#4385) Update the quic-go version. If you are using the squic.ConnDialer, make sure that the SCMP errors are not propagated up the stack to the quic-go transport. --- WORKSPACE | 16 +- gateway/BUILD.bazel | 2 +- gateway/gateway.go | 66 ++++---- go.mod | 29 ++-- go.sum | 76 ++++------ go_deps.bzl | 143 ++++++++---------- .../LICENSE | 27 ---- .../LICENSE | 0 .../LICENSE | 0 licenses/data/org_golang_x_sys/LICENSE | 0 nogo.json | 8 +- .../com_github_quic_go_quic_go/BUILD.bazel | 3 + patches/com_github_quic_go_quic_go/README.md | 8 + .../com_github_quic_go_quic_go/ignore.patch | 12 ++ pkg/snet/dispatcher.go | 21 +++ pkg/snet/squic/BUILD.bazel | 4 +- pkg/snet/squic/net.go | 43 ++++-- pkg/snet/squic/net_test.go | 4 +- private/app/appnet/BUILD.bazel | 2 +- private/app/appnet/infraenv.go | 18 ++- scion-pki/certs/BUILD.bazel | 1 + scion-pki/certs/renew.go | 10 +- 22 files changed, 259 insertions(+), 234 deletions(-) delete mode 100644 licenses/data/com_github_marten_seemann_qtls_go1_19/LICENSE rename licenses/data/{com_github_marten_seemann_qtls_go1_18 => com_github_quic_go_qtls_go1_19}/LICENSE (100%) rename licenses/data/{com_github_lucas_clemente_quic_go => com_github_quic_go_quic_go}/LICENSE (100%) mode change 100755 => 100644 licenses/data/org_golang_x_sys/LICENSE create mode 100644 patches/com_github_quic_go_quic_go/BUILD.bazel create mode 100644 patches/com_github_quic_go_quic_go/README.md create mode 100644 patches/com_github_quic_go_quic_go/ignore.patch diff --git a/WORKSPACE b/WORKSPACE index a19a966fe..a978456a5 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -72,7 +72,21 @@ http_archive( ], ) -load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") +load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository") + +# Explictly override golang.org/x/sys. Our github.com/quic-go/quic-go cannot +# compile without at least golang.org/x/sys@v0.2.0. The rules_go version that +# we use (v0.34.0) imports an older version. A recent enough version was only introduced +# in v0.36.0. See: https://github.com/bazelbuild/rules_go/commit/64b9226a3bca997866b8831889ffb9de87405a0d +# +# This version should be kept in sync with the go_deps.bzl file. We can remove it +# once we update the rules_go version. +go_repository( + name = "org_golang_x_sys", + importpath = "golang.org/x/sys", + sum = "h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=", + version = "v0.8.0", +) go_rules_dependencies() diff --git a/gateway/BUILD.bazel b/gateway/BUILD.bazel index 20a9406fb..902fb0db7 100644 --- a/gateway/BUILD.bazel +++ b/gateway/BUILD.bazel @@ -38,9 +38,9 @@ go_library( "//private/service:go_default_library", "//private/svc:go_default_library", "//private/worker:go_default_library", - "@com_github_lucas_clemente_quic_go//:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", + "@com_github_quic_go_quic_go//:go_default_library", "@org_golang_google_grpc//:go_default_library", ], ) diff --git a/gateway/gateway.go b/gateway/gateway.go index d6fe36e58..d2060b8de 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -24,8 +24,8 @@ import ( "strconv" "time" - quic "github.com/lucas-clemente/quic-go" "github.com/prometheus/client_golang/prometheus" + quic "github.com/quic-go/quic-go" "google.golang.org/grpc" "github.com/scionproto/scion/gateway/control" @@ -140,16 +140,6 @@ func (rtf RoutingTableFactory) New( return dataplane.NewRoutingTable(routingChains), nil } -// ignoreSCMP ignores all received SCMP packets. -// -// XXX(scrye): This is needed such that the QUIC server does not shut down when -// receiving a SCMP error. DO NOT REMOVE! -type ignoreSCMP struct{} - -func (ignoreSCMP) Handle(pkt *snet.Packet) error { - return nil -} - // SelectAdvertisedRoutes computes the networks that should be advertised // depending on the state of the last published routing policy file. type SelectAdvertisedRoutes struct { @@ -448,17 +438,21 @@ func (g *Gateway) Run(ctx context.Context) error { return serrors.WrapStr("unable to generate TLS config", err) } - // scionNetwork is the network for all SCION connections, with the exception of the QUIC server - // connection. - scionNetwork := &snet.SCIONNetwork{ + // scionNetworkNoSCMP is the network for the QUIC server connection. Because SCMP errors + // will cause the server's accepts to fail, we ignore SCMP. + scionNetworkNoSCMP := &snet.SCIONNetwork{ LocalIA: localIA, Dispatcher: &snet.DefaultPacketDispatcherService{ // Enable transparent reconnections to the dispatcher Dispatcher: reconnectingDispatcher, - // Forward revocations to Daemon - SCMPHandler: snet.DefaultSCMPHandler{ - RevocationHandler: revocationHandler, - SCMPErrors: g.Metrics.SCMPErrors, + // Discard all SCMP propagation, to avoid accept/read errors on the + // QUIC server/client. + SCMPHandler: snet.SCMPPropagationStopper{ + Handler: snet.DefaultSCMPHandler{ + RevocationHandler: revocationHandler, + SCMPErrors: g.Metrics.SCMPErrors, + }, + Log: log.FromCtx(ctx).Debug, }, SCIONPacketConnMetrics: g.Metrics.SCIONPacketConnMetrics, }, @@ -467,7 +461,7 @@ func (g *Gateway) Run(ctx context.Context) error { // Initialize the UDP/SCION QUIC conn for outgoing Gateway Discovery RPCs and outgoing Prefix // Fetching. Open up a random high port for this. - clientConn, err := scionNetwork.Listen( + clientConn, err := scionNetworkNoSCMP.Listen( context.TODO(), "udp", &net.UDPAddr{IP: g.ControlClientIP}, @@ -480,7 +474,9 @@ func (g *Gateway) Run(ctx context.Context) error { "local_addr", clientConn.LocalAddr()) quicClientDialer := &squic.ConnDialer{ - Conn: clientConn, + Transport: &quic.Transport{ + Conn: clientConn, + }, TLSConfig: ephemeralTLSConfig, } @@ -509,6 +505,23 @@ func (g *Gateway) Run(ctx context.Context) error { "remote_isd_as", ia.String()) } } + + // scionNetwork is the network for all SCION connections, with the exception of the QUIC server + // and client connection. + scionNetwork := &snet.SCIONNetwork{ + LocalIA: localIA, + Dispatcher: &snet.DefaultPacketDispatcherService{ + // Enable transparent reconnections to the dispatcher + Dispatcher: reconnectingDispatcher, + // Forward revocations to Daemon + SCMPHandler: snet.DefaultSCMPHandler{ + RevocationHandler: revocationHandler, + SCMPErrors: g.Metrics.SCMPErrors, + }, + SCIONPacketConnMetrics: g.Metrics.SCIONPacketConnMetrics, + }, + Metrics: g.Metrics.SCIONNetworkMetrics, + } remoteMonitor := &control.RemoteMonitor{ IAs: remoteIAsChannel, RemotesMonitored: rmMetric, @@ -548,19 +561,6 @@ func (g *Gateway) Run(ctx context.Context) error { }() logger.Debug("Remote monitor started.") - // scionNetworkNoSCMP is the network for the QUIC server connection. Because SCMP errors - // will cause the server's accepts to fail, we ignore SCMP. - scionNetworkNoSCMP := &snet.SCIONNetwork{ - LocalIA: localIA, - Dispatcher: &snet.DefaultPacketDispatcherService{ - // Enable transparent reconnections to the dispatcher - Dispatcher: reconnectingDispatcher, - // Discard all SCMP, to avoid accept errors on the QUIC server. - SCMPHandler: ignoreSCMP{}, - SCIONPacketConnMetrics: g.Metrics.SCIONPacketConnMetrics, - }, - Metrics: g.Metrics.SCIONNetworkMetrics, - } serverConn, err := scionNetworkNoSCMP.Listen( context.TODO(), "udp", diff --git a/go.mod b/go.mod index f7bb61162..3826f2586 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/go-chi/chi/v5 v5.0.8 github.com/go-chi/cors v1.2.1 github.com/golang/mock v1.6.0 - github.com/golang/protobuf v1.5.2 + github.com/golang/protobuf v1.5.3 github.com/google/go-cmp v0.5.9 github.com/google/go-containerregistry v0.13.0 github.com/google/gopacket v1.1.19 @@ -21,7 +21,6 @@ require ( github.com/hashicorp/golang-lru v0.6.0 github.com/iancoleman/strcase v0.2.0 github.com/lestrrat-go/jwx v1.2.25 - github.com/lucas-clemente/quic-go v0.29.1 github.com/mattn/go-isatty v0.0.17 github.com/mattn/go-sqlite3 v1.14.17 github.com/olekukonko/tablewriter v0.0.5 @@ -30,6 +29,7 @@ require ( github.com/pelletier/go-toml v1.9.5 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 + github.com/quic-go/quic-go v0.36.3 github.com/sergi/go-diff v1.3.1 github.com/smartystreets/goconvey v1.7.2 github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 @@ -43,9 +43,9 @@ require ( go.uber.org/zap v1.24.0 go4.org/netipx v0.0.0-20230125063823-8449b0a6169f golang.org/x/crypto v0.6.0 - golang.org/x/net v0.7.0 - golang.org/x/sync v0.1.0 - golang.org/x/tools v0.6.0 + golang.org/x/net v0.10.0 + golang.org/x/sync v0.2.0 + golang.org/x/tools v0.9.1 google.golang.org/grpc v1.53.0 google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 google.golang.org/protobuf v1.28.1 @@ -67,9 +67,10 @@ require ( github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/swag v0.21.1 // indirect - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/goccy/go-json v0.9.11 // indirect github.com/google/go-querystring v1.0.1-0.20190318165438-c8c88dbee036 // indirect + github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -85,21 +86,20 @@ require ( github.com/lestrrat-go/option v1.0.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect - github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect - github.com/nxadm/tail v1.4.8 // indirect - github.com/onsi/ginkgo v1.16.4 // indirect + github.com/onsi/ginkgo/v2 v2.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/perimeterx/marshmallow v1.1.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect + github.com/quic-go/qtls-go1-19 v0.3.3 // indirect + github.com/quic-go/qtls-go1-20 v0.2.3 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/smartystreets/assertions v1.2.0 // indirect @@ -111,13 +111,12 @@ require ( github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/mod v0.8.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/uint128 v1.2.0 // indirect modernc.org/cc/v3 v3.40.0 // indirect diff --git a/go.sum b/go.sum index 4568a3f26..554c90224 100644 --- a/go.sum +++ b/go.sum @@ -106,8 +106,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/getkin/kin-openapi v0.114.0 h1:ar7QiJpDdlR+zSyPjrLf8mNnpoFP/lI90XcywMCFNe8= @@ -127,14 +125,15 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU= github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= @@ -170,8 +169,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -208,6 +208,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -230,7 +231,6 @@ github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -280,8 +280,6 @@ github.com/lestrrat-go/jwx v1.2.25 h1:tAx93jN2SdPvFn08fHNAhqFJazn5mBBOB8Zli0g0ot github.com/lestrrat-go/jwx v1.2.25/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY= github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= -github.com/lucas-clemente/quic-go v0.29.1 h1:Z+WMJ++qMLhvpFkRZA+jl3BTxUjm415YBmWanXB8zP0= -github.com/lucas-clemente/quic-go v0.29.1/go.mod h1:CTcNfLYJS2UuRNB+zcNlgvkjBhxX6Hm3WUxxAQx2mgE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -289,10 +287,6 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM= -github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= -github.com/marten-seemann/qtls-go1-19 v0.1.0 h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK5df3GufyYYU= -github.com/marten-seemann/qtls-go1-19 v0.1.0/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -317,18 +311,11 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwd github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= +github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= +github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= +github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -375,6 +362,12 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/quic-go/qtls-go1-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE= +github.com/quic-go/qtls-go1-19 v0.3.3/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.2.3 h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI= +github.com/quic-go/qtls-go1-20 v0.2.3/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +github.com/quic-go/quic-go v0.36.3 h1:f+yOqeGhMoRX7/M3wmEw/djhzKWr15FtQysox85/834= +github.com/quic-go/quic-go v0.36.3/go.mod h1:qxQumdeKw5GmWs1OsTZZnOxzSI+RJWuhf1O8FN35L2o= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -483,8 +476,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= +golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -509,11 +502,10 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -536,7 +528,6 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -551,8 +542,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -575,11 +566,10 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -590,10 +580,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -619,7 +606,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -633,8 +619,8 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -645,8 +631,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -696,14 +682,13 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -814,11 +799,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/go_deps.bzl b/go_deps.bzl index 0d1273f01..6bc4b5922 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -118,8 +118,8 @@ def go_deps(): go_repository( name = "com_github_chzyer_readline", importpath = "github.com/chzyer/readline", - sum = "h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=", - version = "v0.0.0-20180603132655-2972be24d48e", + sum = "h1:lSwwFrbNviGePhkewF1az4oLmcwqCZijQ2/Wi3BGHAI=", + version = "v1.5.0", ) go_repository( name = "com_github_chzyer_test", @@ -355,6 +355,12 @@ def go_deps(): sum = "h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=", version = "v0.5.1", ) + go_repository( + name = "com_github_go_logr_logr", + importpath = "github.com/go-logr/logr", + sum = "h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=", + version = "v1.2.4", + ) go_repository( name = "com_github_go_openapi_jsonpointer", importpath = "github.com/go-openapi/jsonpointer", @@ -394,8 +400,8 @@ def go_deps(): go_repository( name = "com_github_go_task_slim_sprig", importpath = "github.com/go-task/slim-sprig", - sum = "h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=", - version = "v0.0.0-20210107165309-348f09dbbbc0", + sum = "h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=", + version = "v0.0.0-20230315185526-52ccab3ef572", ) go_repository( name = "com_github_go_test_deep", @@ -442,8 +448,8 @@ def go_deps(): go_repository( name = "com_github_golang_protobuf", importpath = "github.com/golang/protobuf", - sum = "h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=", - version = "v1.5.2", + sum = "h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=", + version = "v1.5.3", ) go_repository( name = "com_github_golangci_lint_1", @@ -613,12 +619,6 @@ def go_deps(): sum = "h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=", version = "v0.10.1", ) - go_repository( - name = "com_github_hpcloud_tail", - importpath = "github.com/hpcloud/tail", - sum = "h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=", - version = "v1.0.0", - ) go_repository( name = "com_github_iancoleman_strcase", importpath = "github.com/iancoleman/strcase", @@ -628,8 +628,8 @@ def go_deps(): go_repository( name = "com_github_ianlancetaylor_demangle", importpath = "github.com/ianlancetaylor/demangle", - sum = "h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI=", - version = "v0.0.0-20200824232613-28f6c0f3b639", + sum = "h1:rcanfLhLDA8nozr/K289V1zcntHr3V+SHlXwzz1ZI2g=", + version = "v0.0.0-20220319035150-800ac71e25c2", ) go_repository( name = "com_github_inconshreveable_mousetrap", @@ -805,13 +805,6 @@ def go_deps(): sum = "h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=", version = "v1.0.0", ) - go_repository( - name = "com_github_lucas_clemente_quic_go", - build_directives = ["gazelle:exclude internal/qtls/go116.go"], # XXX(matzf): exclude go-1.16 file that should not be built, but gazelle does not properly understand the release tags. - importpath = "github.com/lucas-clemente/quic-go", - sum = "h1:Z+WMJ++qMLhvpFkRZA+jl3BTxUjm415YBmWanXB8zP0=", - version = "v0.29.1", - ) go_repository( name = "com_github_magiconair_properties", importpath = "github.com/magiconair/properties", @@ -824,24 +817,6 @@ def go_deps(): sum = "h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=", version = "v0.7.7", ) - go_repository( - name = "com_github_marten_seemann_qpack", - importpath = "github.com/marten-seemann/qpack", - sum = "h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs=", - version = "v0.2.1", - ) - go_repository( - name = "com_github_marten_seemann_qtls_go1_18", - importpath = "github.com/marten-seemann/qtls-go1-18", - sum = "h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM=", - version = "v0.1.2", - ) - go_repository( - name = "com_github_marten_seemann_qtls_go1_19", - importpath = "github.com/marten-seemann/qtls-go1-19", - sum = "h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK5df3GufyYYU=", - version = "v0.1.0", - ) go_repository( name = "com_github_matryer_moq", importpath = "github.com/matryer/moq", @@ -938,12 +913,6 @@ def go_deps(): sum = "h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=", version = "v0.0.0-20200227124842-a10e7caefd8e", ) - go_repository( - name = "com_github_nxadm_tail", - importpath = "github.com/nxadm/tail", - sum = "h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=", - version = "v1.4.8", - ) go_repository( name = "com_github_olekukonko_tablewriter", importpath = "github.com/olekukonko/tablewriter", @@ -951,16 +920,16 @@ def go_deps(): version = "v0.0.5", ) go_repository( - name = "com_github_onsi_ginkgo", - importpath = "github.com/onsi/ginkgo", - sum = "h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=", - version = "v1.16.4", + name = "com_github_onsi_ginkgo_v2", + importpath = "github.com/onsi/ginkgo/v2", + sum = "h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=", + version = "v2.9.5", ) go_repository( name = "com_github_onsi_gomega", importpath = "github.com/onsi/gomega", - sum = "h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=", - version = "v1.13.0", + sum = "h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=", + version = "v1.27.6", ) go_repository( name = "com_github_opencontainers_go_digest", @@ -1046,6 +1015,34 @@ def go_deps(): sum = "h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=", version = "v0.8.0", ) + go_repository( + name = "com_github_quic_go_qpack", + importpath = "github.com/quic-go/qpack", + sum = "h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=", + version = "v0.4.0", + ) + go_repository( + name = "com_github_quic_go_qtls_go1_19", + importpath = "github.com/quic-go/qtls-go1-19", + sum = "h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE=", + version = "v0.3.3", + ) + go_repository( + name = "com_github_quic_go_qtls_go1_20", + importpath = "github.com/quic-go/qtls-go1-20", + sum = "h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI=", + version = "v0.2.3", + ) + go_repository( + name = "com_github_quic_go_quic_go", + importpath = "github.com/quic-go/quic-go", + patch_args = ["-p1"], # keep + patches = [ + "@//patches/com_github_quic_go_quic_go:ignore.patch", # keep + ], + sum = "h1:f+yOqeGhMoRX7/M3wmEw/djhzKWr15FtQysox85/834=", + version = "v0.36.3", + ) go_repository( name = "com_github_ravenox_go_jsoncommentstrip", importpath = "github.com/RaveNoX/go-jsoncommentstrip", @@ -1982,24 +1979,12 @@ def go_deps(): sum = "h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=", version = "v2.1.0", ) - go_repository( - name = "in_gopkg_fsnotify_v1", - importpath = "gopkg.in/fsnotify.v1", - sum = "h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=", - version = "v1.4.7", - ) go_repository( name = "in_gopkg_ini_v1", importpath = "gopkg.in/ini.v1", sum = "h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=", version = "v1.67.0", ) - go_repository( - name = "in_gopkg_tomb_v1", - importpath = "gopkg.in/tomb.v1", - sum = "h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=", - version = "v1.0.0-20141024135613-dd632973f1e7", - ) go_repository( name = "in_gopkg_yaml_v2", importpath = "gopkg.in/yaml.v2", @@ -2111,8 +2096,8 @@ def go_deps(): go_repository( name = "org_golang_x_exp", importpath = "golang.org/x/exp", - sum = "h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=", - version = "v0.0.0-20220722155223-a9213eeb770e", + sum = "h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=", + version = "v0.0.0-20221205204356-47842c84f3db", ) go_repository( name = "org_golang_x_exp_typeparams", @@ -2141,14 +2126,14 @@ def go_deps(): go_repository( name = "org_golang_x_mod", importpath = "golang.org/x/mod", - sum = "h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=", - version = "v0.8.0", + sum = "h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=", + version = "v0.10.0", ) go_repository( name = "org_golang_x_net", importpath = "golang.org/x/net", - sum = "h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=", - version = "v0.7.0", + sum = "h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=", + version = "v0.10.0", ) go_repository( name = "org_golang_x_oauth2", @@ -2159,26 +2144,26 @@ def go_deps(): go_repository( name = "org_golang_x_sync", importpath = "golang.org/x/sync", - sum = "h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=", - version = "v0.1.0", + sum = "h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=", + version = "v0.2.0", ) go_repository( name = "org_golang_x_sys", importpath = "golang.org/x/sys", - sum = "h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=", - version = "v0.5.0", + sum = "h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=", + version = "v0.8.0", ) go_repository( name = "org_golang_x_term", importpath = "golang.org/x/term", - sum = "h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=", - version = "v0.5.0", + sum = "h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=", + version = "v0.8.0", ) go_repository( name = "org_golang_x_text", importpath = "golang.org/x/text", - sum = "h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=", - version = "v0.7.0", + sum = "h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=", + version = "v0.9.0", ) go_repository( name = "org_golang_x_time", @@ -2189,8 +2174,8 @@ def go_deps(): go_repository( name = "org_golang_x_tools", importpath = "golang.org/x/tools", - sum = "h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=", - version = "v0.6.0", + sum = "h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=", + version = "v0.9.1", ) go_repository( name = "org_golang_x_xerrors", diff --git a/licenses/data/com_github_marten_seemann_qtls_go1_19/LICENSE b/licenses/data/com_github_marten_seemann_qtls_go1_19/LICENSE deleted file mode 100644 index 6a66aea5e..000000000 --- a/licenses/data/com_github_marten_seemann_qtls_go1_19/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/com_github_marten_seemann_qtls_go1_18/LICENSE b/licenses/data/com_github_quic_go_qtls_go1_19/LICENSE similarity index 100% rename from licenses/data/com_github_marten_seemann_qtls_go1_18/LICENSE rename to licenses/data/com_github_quic_go_qtls_go1_19/LICENSE diff --git a/licenses/data/com_github_lucas_clemente_quic_go/LICENSE b/licenses/data/com_github_quic_go_quic_go/LICENSE similarity index 100% rename from licenses/data/com_github_lucas_clemente_quic_go/LICENSE rename to licenses/data/com_github_quic_go_quic_go/LICENSE diff --git a/licenses/data/org_golang_x_sys/LICENSE b/licenses/data/org_golang_x_sys/LICENSE old mode 100755 new mode 100644 diff --git a/nogo.json b/nogo.json index 8e6ff5d7f..d87461c69 100644 --- a/nogo.json +++ b/nogo.json @@ -44,7 +44,6 @@ "gazelle/cmd/gazelle/diff.go": "", "/in_gopkg_yaml_v2/decode.go": "https://github.com/go-yaml/yaml/pull/492", "/com_github_mattn_go_sqlite3": "", - "/com_github_lucas_clemente_quic_go": "", "/com_github_cloudflare_sidh": "", "/com_github_vishvananda_netlink": "" } @@ -183,9 +182,6 @@ "com_github_hashicorp_hcl": "", "com_github_stretchr_testify/assert": "", "com_github_spf13_afero": "", - "com_github_marten_seemann_qtls_go1_16": "", - "com_github_marten_seemann_qtls_go1_17": "", - "com_github_lucas_clemente_quic_go": "", "com_github_lestrrat_go_jwx": "", "com_github_pelletier_go_toml": "", "com_github_mdlayher_raw": "", @@ -197,7 +193,6 @@ "com_github_spf13_viper": "", "com_github_labstack_echo_v4": "", "com_github_deepmap_oapi_codegen": "", - "pkg/private/serrors/errors.go": "err shadowed", "pkg/slayers/path/scion/raw.go": "err shadowed", "pkg/scrypto/cppki/trc.go": "err shadowed", @@ -211,7 +206,8 @@ "org_golang_x_crypto/ed25519/internal/edwards25519": "", "com_github_vishvananda_netlink/nl": "", "com_github_deepmap_oapi_codegen/pkg/codegen": "", - "com_github_bazelbuild_buildtools": "" + "com_github_bazelbuild_buildtools": "", + "com_github_quic_go_quic_go/internal/wire/ack_frame.go": "" } } } diff --git a/patches/com_github_quic_go_quic_go/BUILD.bazel b/patches/com_github_quic_go_quic_go/BUILD.bazel new file mode 100644 index 000000000..039ab957b --- /dev/null +++ b/patches/com_github_quic_go_quic_go/BUILD.bazel @@ -0,0 +1,3 @@ +exports_files(glob([ + "*.patch", +])) diff --git a/patches/com_github_quic_go_quic_go/README.md b/patches/com_github_quic_go_quic_go/README.md new file mode 100644 index 000000000..0e0f4167c --- /dev/null +++ b/patches/com_github_quic_go_quic_go/README.md @@ -0,0 +1,8 @@ +# quic-go patches + +The [ignore.patch](./ignore.patch) ignores the qtls-go1-20 dependency that is +generated by gazelle. qtls-go1-20 requires Go version 1.20, and is hidden behind +a build tag that gazelle ignores. Bazel then tries to build qtls-go1-20 with Go 1.19, +which obviously does not work. + +This patch can be removed as soon as we update the Go version. diff --git a/patches/com_github_quic_go_quic_go/ignore.patch b/patches/com_github_quic_go_quic_go/ignore.patch new file mode 100644 index 000000000..a4375e51f --- /dev/null +++ b/patches/com_github_quic_go_quic_go/ignore.patch @@ -0,0 +1,12 @@ +diff --git a/internal/qtls/BUILD.bazel b/internal/qtls/BUILD.bazel +index 0dd9af2..f500bc9 100644 +--- a/internal/qtls/BUILD.bazel ++++ b/internal/qtls/BUILD.bazel +@@ -12,7 +12,6 @@ go_library( + visibility = ["//:__subpackages__"], + deps = [ + "@com_github_quic_go_qtls_go1_19//:qtls-go1-19", +- "@com_github_quic_go_qtls_go1_20//:qtls-go1-20", + ], + ) + diff --git a/pkg/snet/dispatcher.go b/pkg/snet/dispatcher.go index bfc1180a0..99fb8cde0 100644 --- a/pkg/snet/dispatcher.go +++ b/pkg/snet/dispatcher.go @@ -143,3 +143,24 @@ func (h *DefaultSCMPHandler) handleSCMPRev(typeCode slayers.SCMPTypeCode, } return &OpError{typeCode: typeCode, revInfo: revInfo} } + +// SCMPPropagationStopper wraps an SCMP handler and stops propagation of the +// SCMP errors up the stack. This can be necessary if the client code aborts on +// unexpected errors. This is a temporary solution until we address +// https://github.com/scionproto/scion/issues/4389. +// +// EXPERIMENTAL: This handler is experimental and may be removed in the future. +type SCMPPropagationStopper struct { + // Handler is the wrapped handler. + Handler SCMPHandler + // Log is an optional function that is called when the wrapped handler + // returns an error and propagation is stopped. + Log func(msg string, ctx ...any) +} + +func (h SCMPPropagationStopper) Handle(pkt *Packet) error { + if err := h.Handler.Handle(pkt); err != nil && h.Log != nil { + h.Log("Stopped SCMP error propagation", "err", err) + } + return nil +} diff --git a/pkg/snet/squic/BUILD.bazel b/pkg/snet/squic/BUILD.bazel index d19c2c64a..b05803f89 100644 --- a/pkg/snet/squic/BUILD.bazel +++ b/pkg/snet/squic/BUILD.bazel @@ -9,7 +9,7 @@ go_library( "//pkg/log:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/snet:go_default_library", - "@com_github_lucas_clemente_quic_go//:go_default_library", + "@com_github_quic_go_quic_go//:go_default_library", ], ) @@ -23,7 +23,7 @@ go_test( "//pkg/proto/control_plane:go_default_library", "//pkg/proto/control_plane/mock_control_plane:go_default_library", "@com_github_golang_mock//gomock:go_default_library", - "@com_github_lucas_clemente_quic_go//:go_default_library", + "@com_github_quic_go_quic_go//:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", "@org_golang_google_grpc//:go_default_library", diff --git a/pkg/snet/squic/net.go b/pkg/snet/squic/net.go index dc0d5f01c..e20d21e45 100644 --- a/pkg/snet/squic/net.go +++ b/pkg/snet/squic/net.go @@ -24,7 +24,7 @@ import ( "sync" "time" - "github.com/lucas-clemente/quic-go" + "github.com/quic-go/quic-go" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/serrors" @@ -48,14 +48,14 @@ const streamAcceptTimeout = 5 * time.Second // ConnListener wraps a quic.Listener as a net.Listener. type ConnListener struct { - quic.Listener + *quic.Listener ctx context.Context cancel func() } // NewConnListener constructs a new listener with the appropriate buffers set. -func NewConnListener(l quic.Listener) *ConnListener { +func NewConnListener(l *quic.Listener) *ConnListener { ctx, cancel := context.WithCancel(context.Background()) c := &ConnListener{ Listener: l, @@ -347,10 +347,16 @@ func (c *acceptingConn) Close() error { // ConnDialer dials a net.Conn over a QUIC stream. type ConnDialer struct { - // Conn is the connection to initiate QUIC Sessions on. It can be shared + // Conn is the transport to initiate QUIC Sessions on. It can be shared // between clients and servers, because QUIC connection IDs are used to // demux the packets. - Conn net.PacketConn + // + // Note: When creating the transport, ensure that the SCMP errors are not + // propagated. You can for example use + // [github.com/scionproto/scion/pkg/snet.SCMPPropagationStopper]. Otherwise, + // the QUIC transport will close the listening side on SCMP errors and enter + // a broken state. + Transport *quic.Transport // TLSConfig is the client's TLS configuration for starting QUIC connections. TLSConfig *tls.Config // QUICConfig is the client's QUIC configuration. @@ -363,15 +369,19 @@ type ConnDialer struct { // fails due to a SERVER_BUSY error. Timers, number of attempts are EXPERIMENTAL // and subject to change. func (d ConnDialer) Dial(ctx context.Context, dst net.Addr) (net.Conn, error) { - addressStr := computeAddressStr(dst) - if d.TLSConfig == nil { return nil, serrors.New("tls.Config not set") } + serverName := d.TLSConfig.ServerName + if serverName == "" { + serverName = computeServerName(dst) + } + var session quic.Connection for sleep := 2 * time.Millisecond; ctx.Err() == nil; sleep = sleep * 2 { // Clone TLS config to avoid data races. tlsConfig := d.TLSConfig.Clone() + tlsConfig.ServerName = serverName // Clone QUIC config to avoid data races, if it exists. var quicConfig *quic.Config if d.QUICConfig != nil { @@ -379,7 +389,7 @@ func (d ConnDialer) Dial(ctx context.Context, dst net.Addr) (net.Conn, error) { } var err error - session, err = quic.DialContext(ctx, d.Conn, dst, addressStr, tlsConfig, quicConfig) + session, err = d.Transport.Dial(ctx, dst, tlsConfig, quicConfig) if err == nil { break } @@ -410,13 +420,22 @@ func (d ConnDialer) Dial(ctx context.Context, dst net.Addr) (net.Conn, error) { } -// computeAddressStr returns a parseable version of the SCION address for use +// computeServerName returns a parseable version of the SCION address for use // with QUIC SNI. -func computeAddressStr(address net.Addr) string { +func computeServerName(address net.Addr) string { + // XXX(roosd): Special case snet.UDPAddr because its string encoding is not + // processable by net.SplitHostPort. if v, ok := address.(*snet.UDPAddr); ok { - return fmt.Sprintf("[%s,%s]:%d", v.IA, v.Host.IP, v.Host.Port) + return fmt.Sprintf("%s,%s", v.IA, v.Host.IP) + } + host := address.String() + sni, _, err := net.SplitHostPort(host) + if err != nil { + // It's ok if net.SplitHostPort returns an error. it could be a + // hostname/IP address without a port. + sni = host } - return address.String() + return sni } // acceptedConn is a net.Conn wrapper for a QUIC stream. diff --git a/pkg/snet/squic/net_test.go b/pkg/snet/squic/net_test.go index 5c99a5d89..a75036503 100644 --- a/pkg/snet/squic/net_test.go +++ b/pkg/snet/squic/net_test.go @@ -27,7 +27,7 @@ import ( "time" "github.com/golang/mock/gomock" - "github.com/lucas-clemente/quic-go" + "github.com/quic-go/quic-go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" @@ -209,7 +209,7 @@ func netListener(t *testing.T) (net.Listener, *net.UDPConn) { func connDialer(t *testing.T) *squic.ConnDialer { return &squic.ConnDialer{ - Conn: newConn(t), + Transport: &quic.Transport{Conn: newConn(t)}, TLSConfig: tlsConfig(t), } } diff --git a/private/app/appnet/BUILD.bazel b/private/app/appnet/BUILD.bazel index 68f765018..6762e1fd6 100644 --- a/private/app/appnet/BUILD.bazel +++ b/private/app/appnet/BUILD.bazel @@ -23,7 +23,7 @@ go_library( "//private/env:go_default_library", "//private/svc:go_default_library", "//private/trust:go_default_library", - "@com_github_lucas_clemente_quic_go//:go_default_library", + "@com_github_quic_go_quic_go//:go_default_library", ], ) diff --git a/private/app/appnet/infraenv.go b/private/app/appnet/infraenv.go index c9fdd7646..e1f73c73c 100644 --- a/private/app/appnet/infraenv.go +++ b/private/app/appnet/infraenv.go @@ -31,7 +31,7 @@ import ( "net" "time" - "github.com/lucas-clemente/quic-go" + "github.com/quic-go/quic-go" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/daemon" @@ -150,15 +150,18 @@ func (nc *NetworkConfig) QUICStack() (*QUICStack, error) { VerifyConnection: nc.QUIC.TLSVerifier.VerifyConnection, NextProtos: []string{"SCION"}, } + clientTransport := &quic.Transport{ + Conn: client, + } return &QUICStack{ Listener: squic.NewConnListener(listener), InsecureDialer: &squic.ConnDialer{ - Conn: client, + Transport: clientTransport, TLSConfig: insecureClientTLSConfig, }, Dialer: &squic.ConnDialer{ - Conn: client, + Transport: clientTransport, TLSConfig: clientTLSConfig, }, RedirectCloser: cancel, @@ -336,8 +339,13 @@ func (nc *NetworkConfig) initQUICSockets() (net.PacketConn, net.PacketConn, erro clientNet := &snet.SCIONNetwork{ LocalIA: nc.IA, Dispatcher: &snet.DefaultPacketDispatcherService{ - Dispatcher: dispatcherService, - SCMPHandler: nc.SCMPHandler, + Dispatcher: dispatcherService, + // Discard all SCMP propagation, to avoid read errors on the QUIC + // client. + SCMPHandler: snet.SCMPPropagationStopper{ + Handler: nc.SCMPHandler, + Log: log.Debug, + }, SCIONPacketConnMetrics: nc.SCIONPacketConnMetrics, }, Metrics: nc.SCIONNetworkMetrics, diff --git a/scion-pki/certs/BUILD.bazel b/scion-pki/certs/BUILD.bazel index 5c4d46806..21de49c53 100644 --- a/scion-pki/certs/BUILD.bazel +++ b/scion-pki/certs/BUILD.bazel @@ -49,6 +49,7 @@ go_library( "//scion-pki/key:go_default_library", "@com_github_opentracing_opentracing_go//:go_default_library", "@com_github_pkg_errors//:go_default_library", + "@com_github_quic_go_quic_go//:go_default_library", "@com_github_spf13_cobra//:go_default_library", "@org_golang_google_grpc//resolver:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", diff --git a/scion-pki/certs/renew.go b/scion-pki/certs/renew.go index eea541680..4bb546a18 100644 --- a/scion-pki/certs/renew.go +++ b/scion-pki/certs/renew.go @@ -27,6 +27,7 @@ import ( "strconv" "time" + "github.com/quic-go/quic-go" "github.com/spf13/cobra" "google.golang.org/grpc/resolver" "google.golang.org/protobuf/proto" @@ -744,8 +745,11 @@ func (r *renewer) requestRemote( LocalIA: local.IA, Dispatcher: &snet.DefaultPacketDispatcherService{ Dispatcher: reliable.NewDispatcher(r.Disatcher), - SCMPHandler: snet.DefaultSCMPHandler{ - RevocationHandler: daemon.RevHandler{Connector: r.Daemon}, + SCMPHandler: snet.SCMPPropagationStopper{ + Handler: snet.DefaultSCMPHandler{ + RevocationHandler: daemon.RevHandler{Connector: r.Daemon}, + }, + Log: log.FromCtx(ctx).Debug, }, }, } @@ -770,7 +774,7 @@ func (r *renewer) requestRemote( SVCResolutionFraction: 1, }, Dialer: squic.ConnDialer{ - Conn: conn, + Transport: &quic.Transport{Conn: conn}, TLSConfig: &tls.Config{ InsecureSkipVerify: true, NextProtos: []string{"SCION"}, From 783896ee19158e94978b1d2d7cbed564b3b22c55 Mon Sep 17 00:00:00 2001 From: Sebastian Leisinger Date: Mon, 11 Sep 2023 17:08:39 +0200 Subject: [PATCH 051/255] build: update to Go 1.21.1 (#4378) Update Go version to 1.21.1 Additionally, upgrade various build dependencies. Co-authored-by: Dominik Roos --- .bazelversion | 2 +- .golangcilint.yml | 10 - BUILD.bazel | 5 + Makefile | 5 +- WORKSPACE | 19 +- control/drkey/arc_test.go | 1 + daemon/internal/servers/BUILD.bazel | 4 +- go.mod | 11 +- go.sum | 22 +- go_deps.bzl | 756 ++---------------- .../LICENSE | 0 .../cmd/vendor/golang.org/x/crypto/LICENSE | 27 - .../LICENSE | 1 + nogo.json | 13 +- pkg/private/serrors/testdata/error-list.log | 2 +- .../serrors/testdata/error-with-context.log | 2 +- .../serrors/testdata/new-with-context.log | 2 +- .../serrors/testdata/wrapped-error.log | 2 +- .../serrors/testdata/wrapped-string.log | 2 +- .../serrors/testdata/wrapped-with-string.log | 2 +- pkg/proto/control_plane/cppki.pb.go | 2 +- pkg/proto/control_plane/drkey.pb.go | 2 +- .../seg_detached_extensions.pb.go | 2 +- pkg/proto/control_plane/renewal.pb.go | 2 +- pkg/proto/control_plane/seg.pb.go | 2 +- pkg/proto/control_plane/seg_extensions.pb.go | 2 +- pkg/proto/control_plane/svc_resolution.pb.go | 2 +- pkg/proto/crypto/signed.pb.go | 2 +- pkg/proto/daemon/daemon.pb.go | 2 +- pkg/proto/discovery/discovery.pb.go | 2 +- pkg/proto/drkey/drkey.pb.go | 2 +- pkg/proto/gateway/control.pb.go | 2 +- pkg/proto/gateway/prefix.pb.go | 2 +- pkg/proto/hidden_segment/hidden_segment.pb.go | 2 +- pkg/scrypto/signed/BUILD.bazel | 2 +- pkg/snet/squic/net.go | 4 +- pkg/snet/squic/net_test.go | 2 + private/trust/grpc/BUILD.bazel | 2 +- 38 files changed, 116 insertions(+), 810 deletions(-) rename licenses/data/{com_github_quic_go_qtls_go1_19 => com_github_quic_go_qtls_go1_20}/LICENSE (100%) delete mode 100644 licenses/data/go_sdk/src/cmd/vendor/golang.org/x/crypto/LICENSE rename licenses/data/{go_googleapis => org_golang_google_genproto_googleapis_rpc}/LICENSE (99%) mode change 100755 => 100644 diff --git a/.bazelversion b/.bazelversion index 831446cbd..8a30e8f94 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -5.1.0 +5.4.0 diff --git a/.golangcilint.yml b/.golangcilint.yml index 1b79a3240..32b2a7533 100644 --- a/.golangcilint.yml +++ b/.golangcilint.yml @@ -10,7 +10,6 @@ linters: - typecheck - unused # Extended linters. - - depguard - exportloopref - rowserrcheck - sqlclosecheck @@ -23,15 +22,6 @@ linters-settings: lll: line-length: 100 tab-width: 4 - depguard: - list-type: blacklist - include-go-root: true - packages: "io/ioutil" - packages-with-error-message: - # specify an error message to output when a blacklisted package is used - "io/ioutil": > - "The use of 'io/ioutil' is deprecated. Check - https://pkg.go.dev/io/ioutil for alternatives" errcheck: exclude-functions: - (*github.com/spf13/cobra.Command).MarkFlagRequired diff --git a/BUILD.bazel b/BUILD.bazel index ba817ae8f..e70dded2a 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -91,6 +91,11 @@ gazelle( gazelle( name = "gazelle_update_repos", command = "update-repos", + extra_args = [ + "-prune", + "-from_file=go.mod", + "-to_macro=go_deps.bzl%go_deps", + ], ) go_lint_config( diff --git a/Makefile b/Makefile index e9b251cc3..43fe60d30 100644 --- a/Makefile +++ b/Makefile @@ -30,8 +30,7 @@ go.mod: bazel run --config=quiet @go_sdk//:bin/go -- mod tidy go_deps.bzl: go.mod - @# gazelle is run with "-args"; so our arguments are added to those from the gazelle() rule. - bazel run --verbose_failures --config=quiet //:gazelle_update_repos -- -args -prune -from_file=go.mod -to_macro=go_deps.bzl%go_deps + bazel run --verbose_failures --config=quiet //:gazelle_update_repos @# XXX(matzf): clean up; gazelle update-repose inconsistently inserts blank lines (see bazelbuild/bazel-gazelle#1088). @sed -e '/def go_deps/,$${/^$$/d}' -i go_deps.bzl @@ -93,7 +92,7 @@ GO_BUILD_TAGS_ARG=$(shell bazel build --ui_event_filters=-stdout,-stderr --annou lint-go-golangci: $(info ==> $@) @if [ -t 1 ]; then tty=true; else tty=false; fi; \ - tools/quiet docker run --tty=$$tty --rm -v golangci-lint-modcache:/go -v golangci-lint-buildcache:/root/.cache -v "${PWD}:/src" -w /src golangci/golangci-lint:v1.50.0 golangci-lint run --config=/src/.golangcilint.yml --timeout=3m $(GO_BUILD_TAGS_ARG) --skip-dirs doc ./... + tools/quiet docker run --tty=$$tty --rm -v golangci-lint-modcache:/go -v golangci-lint-buildcache:/root/.cache -v "${PWD}:/src" -w /src golangci/golangci-lint:v1.54.2 golangci-lint run --config=/src/.golangcilint.yml --timeout=3m $(GO_BUILD_TAGS_ARG) --skip-dirs doc ./... lint-go-semgrep: $(info ==> $@) diff --git a/WORKSPACE b/WORKSPACE index a978456a5..491241f5f 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -43,10 +43,10 @@ aspect_bazel_lib_dependencies() # Bazel rules for Golang http_archive( name = "io_bazel_rules_go", - sha256 = "16e9fca53ed6bd4ff4ad76facc9b7b651a89db1689a2877d6fd7b82aa824e366", + sha256 = "278b7ff5a826f3dc10f04feaf0b70d48b68748ccd512d7f98bf442077f043fe3", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.34.0/rules_go-v0.34.0.zip", - "https://github.com/bazelbuild/rules_go/releases/download/v0.34.0/rules_go-v0.34.0.zip", + "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.41.0/rules_go-v0.41.0.zip", + "https://github.com/bazelbuild/rules_go/releases/download/v0.41.0/rules_go-v0.41.0.zip", ], ) @@ -54,21 +54,16 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe go_register_toolchains( nogo = "@//:nogo", - version = "1.19.2", + version = "1.21.1", ) # Gazelle http_archive( name = "bazel_gazelle", - patch_args = ["-p1"], - patches = [ - # PR: https://github.com/bazelbuild/bazel-gazelle/pull/1243 - "@//patches/bazel_gazelle:gazelle.patch", - ], - sha256 = "501deb3d5695ab658e82f6f6f549ba681ea3ca2a5fb7911154b5aa45596183fa", + sha256 = "29218f8e0cebe583643cbf93cae6f971be8a2484cdcfa1e45057658df8d54002", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.26.0/bazel-gazelle-v0.26.0.tar.gz", - "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.26.0/bazel-gazelle-v0.26.0.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.32.0/bazel-gazelle-v0.32.0.tar.gz", + "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.32.0/bazel-gazelle-v0.32.0.tar.gz", ], ) diff --git a/control/drkey/arc_test.go b/control/drkey/arc_test.go index b3e503573..93b90ce32 100644 --- a/control/drkey/arc_test.go +++ b/control/drkey/arc_test.go @@ -81,6 +81,7 @@ func TestLevel1ARC(t *testing.T) { }, } for name, tc := range testCases { + name, tc := name, tc t.Run(name, func(t *testing.T) { t.Parallel() diff --git a/daemon/internal/servers/BUILD.bazel b/daemon/internal/servers/BUILD.bazel index a6291b408..1d1534f2c 100644 --- a/daemon/internal/servers/BUILD.bazel +++ b/daemon/internal/servers/BUILD.bazel @@ -27,9 +27,9 @@ go_library( "//private/revcache:go_default_library", "//private/topology:go_default_library", "//private/trust:go_default_library", + "@com_github_golang_protobuf//ptypes/duration", + "@com_github_golang_protobuf//ptypes/timestamp", "@com_github_opentracing_opentracing_go//:go_default_library", - "@io_bazel_rules_go//proto/wkt:duration_go_proto", - "@io_bazel_rules_go//proto/wkt:timestamp_go_proto", "@org_golang_x_sync//singleflight:go_default_library", ], ) diff --git a/go.mod b/go.mod index 3826f2586..94a5be61d 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/pelletier/go-toml v1.9.5 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 - github.com/quic-go/quic-go v0.36.3 + github.com/quic-go/quic-go v0.38.1 github.com/sergi/go-diff v1.3.1 github.com/smartystreets/goconvey v1.7.2 github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 @@ -46,9 +46,9 @@ require ( golang.org/x/net v0.10.0 golang.org/x/sync v0.2.0 golang.org/x/tools v0.9.1 - google.golang.org/grpc v1.53.0 + google.golang.org/grpc v1.57.0 google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 - google.golang.org/protobuf v1.28.1 + google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v2 v2.4.0 modernc.org/sqlite v1.24.0 ) @@ -98,8 +98,7 @@ require ( github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect - github.com/quic-go/qtls-go1-19 v0.3.3 // indirect - github.com/quic-go/qtls-go1-20 v0.2.3 // indirect + github.com/quic-go/qtls-go1-20 v0.3.3 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/smartystreets/assertions v1.2.0 // indirect @@ -115,7 +114,7 @@ require ( golang.org/x/mod v0.10.0 // indirect golang.org/x/sys v0.8.0 // indirect golang.org/x/text v0.9.0 // indirect - google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/uint128 v1.2.0 // indirect diff --git a/go.sum b/go.sum index 554c90224..6048c5353 100644 --- a/go.sum +++ b/go.sum @@ -362,12 +362,10 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/quic-go/qtls-go1-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE= -github.com/quic-go/qtls-go1-19 v0.3.3/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= -github.com/quic-go/qtls-go1-20 v0.2.3 h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI= -github.com/quic-go/qtls-go1-20 v0.2.3/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= -github.com/quic-go/quic-go v0.36.3 h1:f+yOqeGhMoRX7/M3wmEw/djhzKWr15FtQysox85/834= -github.com/quic-go/quic-go v0.36.3/go.mod h1:qxQumdeKw5GmWs1OsTZZnOxzSI+RJWuhf1O8FN35L2o= +github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM= +github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= +github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE= +github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -756,8 +754,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 h1:lv6/DhyiFFGsmzxbsUUTOkN29II+zeWHxvT8Lpdxsv0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -774,8 +772,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 h1:ijVKWXLMbG/RK63KfOQ1lEVpEApj174fkw073gxZf3w= google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095/go.mod h1:Nr5H8+MlGWr5+xX/STzdoEqJrO+YteqFbMyCsrb6mH0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -790,8 +788,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go_deps.bzl b/go_deps.bzl index 6bc4b5922..b4e2da4fa 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -142,8 +142,8 @@ def go_deps(): go_repository( name = "com_github_cncf_xds_go", importpath = "github.com/cncf/xds/go", - sum = "h1:ACGZRIr7HsgBKHsueQ1yM4WaVaXh21ynwqsF8M8tXhA=", - version = "v0.0.0-20230105202645-06c439db220b", + sum = "h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=", + version = "v0.0.0-20230607035331-e9ce68804cb4", ) go_repository( name = "com_github_codahale_hdrhistogram", @@ -262,14 +262,14 @@ def go_deps(): go_repository( name = "com_github_envoyproxy_go_control_plane", importpath = "github.com/envoyproxy/go-control-plane", - sum = "h1:xdCVXxEe0Y3FQith+0cj2irwZudqGYvecuLB1HtdexY=", - version = "v0.10.3", + sum = "h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA=", + version = "v0.11.1-0.20230524094728-9239064ad72f", ) go_repository( name = "com_github_envoyproxy_protoc_gen_validate", importpath = "github.com/envoyproxy/protoc-gen-validate", - sum = "h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY=", - version = "v0.9.1", + sum = "h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=", + version = "v0.10.1", ) go_repository( name = "com_github_fatih_color", @@ -424,8 +424,8 @@ def go_deps(): go_repository( name = "com_github_golang_glog", importpath = "github.com/golang/glog", - sum = "h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=", - version = "v1.0.0", + sum = "h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=", + version = "v1.1.0", ) go_repository( name = "com_github_golang_groupcache", @@ -1021,27 +1021,17 @@ def go_deps(): sum = "h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=", version = "v0.4.0", ) - go_repository( - name = "com_github_quic_go_qtls_go1_19", - importpath = "github.com/quic-go/qtls-go1-19", - sum = "h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE=", - version = "v0.3.3", - ) go_repository( name = "com_github_quic_go_qtls_go1_20", importpath = "github.com/quic-go/qtls-go1-20", - sum = "h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI=", - version = "v0.2.3", + sum = "h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=", + version = "v0.3.3", ) go_repository( name = "com_github_quic_go_quic_go", importpath = "github.com/quic-go/quic-go", - patch_args = ["-p1"], # keep - patches = [ - "@//patches/com_github_quic_go_quic_go:ignore.patch", # keep - ], - sum = "h1:f+yOqeGhMoRX7/M3wmEw/djhzKWr15FtQysox85/834=", - version = "v0.36.3", + sum = "h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=", + version = "v0.38.1", ) go_repository( name = "com_github_ravenox_go_jsoncommentstrip", @@ -1229,149 +1219,17 @@ def go_deps(): sum = "h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=", version = "v0.105.0", ) - go_repository( - name = "com_google_cloud_go_accessapproval", - importpath = "cloud.google.com/go/accessapproval", - sum = "h1:/nTivgnV/n1CaAeo+ekGexTYUsKEU9jUVkoY5359+3Q=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_accesscontextmanager", - importpath = "cloud.google.com/go/accesscontextmanager", - sum = "h1:CFhNhU7pcD11cuDkQdrE6PQJgv0EXNKNv06jIzbLlCU=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_aiplatform", - importpath = "cloud.google.com/go/aiplatform", - sum = "h1:DBi3Jk9XjCJ4pkkLM4NqKgj3ozUL1wq4l+d3/jTGXAI=", - version = "v1.27.0", - ) - go_repository( - name = "com_google_cloud_go_analytics", - importpath = "cloud.google.com/go/analytics", - sum = "h1:NKw6PpQi6V1O+KsjuTd+bhip9d0REYu4NevC45vtGp8=", - version = "v0.12.0", - ) - go_repository( - name = "com_google_cloud_go_apigateway", - importpath = "cloud.google.com/go/apigateway", - sum = "h1:IIoXKR7FKrEAQhMTz5hK2wiDz2WNFHS7eVr/L1lE/rM=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_apigeeconnect", - importpath = "cloud.google.com/go/apigeeconnect", - sum = "h1:AONoTYJviyv1vS4IkvWzq69gEVdvHx35wKXc+e6wjZQ=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_appengine", - importpath = "cloud.google.com/go/appengine", - sum = "h1:lmG+O5oaR9xNwaRBwE2XoMhwQHsHql5IoiGr1ptdDwU=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_area120", - importpath = "cloud.google.com/go/area120", - sum = "h1:TCMhwWEWhCn8d44/Zs7UCICTWje9j3HuV6nVGMjdpYw=", - version = "v0.6.0", - ) - go_repository( - name = "com_google_cloud_go_artifactregistry", - importpath = "cloud.google.com/go/artifactregistry", - sum = "h1:3d0LRAU1K6vfqCahhl9fx2oGHcq+s5gftdix4v8Ibrc=", - version = "v1.9.0", - ) - go_repository( - name = "com_google_cloud_go_asset", - importpath = "cloud.google.com/go/asset", - sum = "h1:aCrlaLGJWTODJX4G56ZYzJefITKEWNfbjjtHSzWpxW0=", - version = "v1.10.0", - ) - go_repository( - name = "com_google_cloud_go_assuredworkloads", - importpath = "cloud.google.com/go/assuredworkloads", - sum = "h1:hhIdCOowsT1GG5eMCIA0OwK6USRuYTou/1ZeNxCSRtA=", - version = "v1.9.0", - ) - go_repository( - name = "com_google_cloud_go_automl", - importpath = "cloud.google.com/go/automl", - sum = "h1:BMioyXSbg7d7xLibn47cs0elW6RT780IUWr42W8rp2Q=", - version = "v1.8.0", - ) - go_repository( - name = "com_google_cloud_go_baremetalsolution", - importpath = "cloud.google.com/go/baremetalsolution", - sum = "h1:g9KO6SkakcYPcc/XjAzeuUrEOXlYPnMpuiaywYaGrmQ=", - version = "v0.4.0", - ) - go_repository( - name = "com_google_cloud_go_batch", - importpath = "cloud.google.com/go/batch", - sum = "h1:1jvEBY55OH4Sd2FxEXQfxGExFWov1A/IaRe+Z5Z71Fw=", - version = "v0.4.0", - ) - go_repository( - name = "com_google_cloud_go_beyondcorp", - importpath = "cloud.google.com/go/beyondcorp", - sum = "h1:w+4kThysgl0JiKshi2MKDCg2NZgOyqOI0wq2eBZyrzA=", - version = "v0.3.0", - ) go_repository( name = "com_google_cloud_go_bigquery", importpath = "cloud.google.com/go/bigquery", - sum = "h1:Wi4dITi+cf9VYp4VH2T9O41w0kCW0uQTELq2Z6tukN0=", - version = "v1.44.0", - ) - go_repository( - name = "com_google_cloud_go_billing", - importpath = "cloud.google.com/go/billing", - sum = "h1:Xkii76HWELHwBtkQVZvqmSo9GTr0O+tIbRNnMcGdlg4=", - version = "v1.7.0", - ) - go_repository( - name = "com_google_cloud_go_binaryauthorization", - importpath = "cloud.google.com/go/binaryauthorization", - sum = "h1:pL70vXWn9TitQYXBWTK2abHl2JHLwkFRjYw6VflRqEA=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_certificatemanager", - importpath = "cloud.google.com/go/certificatemanager", - sum = "h1:tzbR4UHBbgsewMWUD93JHi8EBi/gHBoSAcY1/sThFGk=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_channel", - importpath = "cloud.google.com/go/channel", - sum = "h1:pNuUlZx0Jb0Ts9P312bmNMuH5IiFWIR4RUtLb70Ke5s=", - version = "v1.9.0", - ) - go_repository( - name = "com_google_cloud_go_cloudbuild", - importpath = "cloud.google.com/go/cloudbuild", - sum = "h1:TAAmCmAlOJ4uNBu6zwAjwhyl/7fLHHxIEazVhr3QBbQ=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_clouddms", - importpath = "cloud.google.com/go/clouddms", - sum = "h1:UhzHIlgFfMr6luVYVNydw/pl9/U5kgtjCMJHnSvoVws=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_cloudtasks", - importpath = "cloud.google.com/go/cloudtasks", - sum = "h1:faUiUgXjW8yVZ7XMnKHKm1WE4OldPBUWWfIRN/3z1dc=", + sum = "h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA=", version = "v1.8.0", ) go_repository( name = "com_google_cloud_go_compute", importpath = "cloud.google.com/go/compute", - sum = "h1:7UGq3QknM33pw5xATlpzeoomNxsacIVvTqTTvbfajmE=", - version = "v1.15.1", + sum = "h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=", + version = "v1.19.1", ) go_repository( name = "com_google_cloud_go_compute_metadata", @@ -1379,143 +1237,11 @@ def go_deps(): sum = "h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=", version = "v0.2.3", ) - go_repository( - name = "com_google_cloud_go_contactcenterinsights", - importpath = "cloud.google.com/go/contactcenterinsights", - sum = "h1:tTQLI/ZvguUf9Hv+36BkG2+/PeC8Ol1q4pBW+tgCx0A=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_container", - importpath = "cloud.google.com/go/container", - sum = "h1:nbEK/59GyDRKKlo1SqpohY1TK8LmJ2XNcvS9Gyom2A0=", - version = "v1.7.0", - ) - go_repository( - name = "com_google_cloud_go_containeranalysis", - importpath = "cloud.google.com/go/containeranalysis", - sum = "h1:2824iym832ljKdVpCBnpqm5K94YT/uHTVhNF+dRTXPI=", - version = "v0.6.0", - ) - go_repository( - name = "com_google_cloud_go_datacatalog", - importpath = "cloud.google.com/go/datacatalog", - sum = "h1:6kZ4RIOW/uT7QWC5SfPfq/G8sYzr/v+UOmOAxy4Z1TE=", - version = "v1.8.0", - ) - go_repository( - name = "com_google_cloud_go_dataflow", - importpath = "cloud.google.com/go/dataflow", - sum = "h1:CW3541Fm7KPTyZjJdnX6NtaGXYFn5XbFC5UcjgALKvU=", - version = "v0.7.0", - ) - go_repository( - name = "com_google_cloud_go_dataform", - importpath = "cloud.google.com/go/dataform", - sum = "h1:vLwowLF2ZB5J5gqiZCzv076lDI/Rd7zYQQFu5XO1PSg=", - version = "v0.5.0", - ) - go_repository( - name = "com_google_cloud_go_datafusion", - importpath = "cloud.google.com/go/datafusion", - sum = "h1:j5m2hjWovTZDTQak4MJeXAR9yN7O+zMfULnjGw/OOLg=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_datalabeling", - importpath = "cloud.google.com/go/datalabeling", - sum = "h1:dp8jOF21n/7jwgo/uuA0RN8hvLcKO4q6s/yvwevs2ZM=", - version = "v0.6.0", - ) - go_repository( - name = "com_google_cloud_go_dataplex", - importpath = "cloud.google.com/go/dataplex", - sum = "h1:cNxeA2DiWliQGi21kPRqnVeQ5xFhNoEjPRt1400Pm8Y=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_dataproc", - importpath = "cloud.google.com/go/dataproc", - sum = "h1:gVOqNmElfa6n/ccG/QDlfurMWwrK3ezvy2b2eDoCmS0=", - version = "v1.8.0", - ) - go_repository( - name = "com_google_cloud_go_dataqna", - importpath = "cloud.google.com/go/dataqna", - sum = "h1:gx9jr41ytcA3dXkbbd409euEaWtofCVXYBvJz3iYm18=", - version = "v0.6.0", - ) go_repository( name = "com_google_cloud_go_datastore", importpath = "cloud.google.com/go/datastore", - sum = "h1:4siQRf4zTiAVt/oeH4GureGkApgb2vtPQAtOmhpqQwE=", - version = "v1.10.0", - ) - go_repository( - name = "com_google_cloud_go_datastream", - importpath = "cloud.google.com/go/datastream", - sum = "h1:PgIgbhedBtYBU6POGXFMn2uSl9vpqubc3ewTNdcU8Mk=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_deploy", - importpath = "cloud.google.com/go/deploy", - sum = "h1:kI6dxt8Ml0is/x7YZjLveTvR7YPzXAUD/8wQZ2nH5zA=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_dialogflow", - importpath = "cloud.google.com/go/dialogflow", - sum = "h1:HYHVOkoxQ9bSfNIelSZYNAtUi4CeSrCnROyOsbOqPq8=", - version = "v1.19.0", - ) - go_repository( - name = "com_google_cloud_go_dlp", - importpath = "cloud.google.com/go/dlp", - sum = "h1:9I4BYeJSVKoSKgjr70fLdRDumqcUeVmHV4fd5f9LR6Y=", - version = "v1.7.0", - ) - go_repository( - name = "com_google_cloud_go_documentai", - importpath = "cloud.google.com/go/documentai", - sum = "h1:jfq09Fdjtnpnmt/MLyf6A3DM3ynb8B2na0K+vSXvpFM=", - version = "v1.10.0", - ) - go_repository( - name = "com_google_cloud_go_domains", - importpath = "cloud.google.com/go/domains", - sum = "h1:pu3JIgC1rswIqi5romW0JgNO6CTUydLYX8zyjiAvO1c=", - version = "v0.7.0", - ) - go_repository( - name = "com_google_cloud_go_edgecontainer", - importpath = "cloud.google.com/go/edgecontainer", - sum = "h1:hd6J2n5dBBRuAqnNUEsKWrp6XNPKsaxwwIyzOPZTokk=", - version = "v0.2.0", - ) - go_repository( - name = "com_google_cloud_go_errorreporting", - importpath = "cloud.google.com/go/errorreporting", - sum = "h1:kj1XEWMu8P0qlLhm3FwcaFsUvXChV/OraZwA70trRR0=", - version = "v0.3.0", - ) - go_repository( - name = "com_google_cloud_go_essentialcontacts", - importpath = "cloud.google.com/go/essentialcontacts", - sum = "h1:b6csrQXCHKQmfo9h3dG/pHyoEh+fQG1Yg78a53LAviY=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_eventarc", - importpath = "cloud.google.com/go/eventarc", - sum = "h1:AgCqrmMMIcel5WWKkzz5EkCUKC3Rl5LNMMYsS+LvsI0=", - version = "v1.8.0", - ) - go_repository( - name = "com_google_cloud_go_filestore", - importpath = "cloud.google.com/go/filestore", - sum = "h1:yjKOpzvqtDmL5AXbKttLc8j0hL20kuC1qPdy5HPcxp0=", - version = "v1.4.0", + sum = "h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=", + version = "v1.1.0", ) go_repository( name = "com_google_cloud_go_firestore", @@ -1523,335 +1249,17 @@ def go_deps(): sum = "h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA=", version = "v1.9.0", ) - go_repository( - name = "com_google_cloud_go_functions", - importpath = "cloud.google.com/go/functions", - sum = "h1:35tgv1fQOtvKqH/uxJMzX3w6usneJ0zXpsFr9KAVhNE=", - version = "v1.9.0", - ) - go_repository( - name = "com_google_cloud_go_gaming", - importpath = "cloud.google.com/go/gaming", - sum = "h1:97OAEQtDazAJD7yh/kvQdSCQuTKdR0O+qWAJBZJ4xiA=", - version = "v1.8.0", - ) - go_repository( - name = "com_google_cloud_go_gkebackup", - importpath = "cloud.google.com/go/gkebackup", - sum = "h1:4K+jiv4ocqt1niN8q5Imd8imRoXBHTrdnJVt/uFFxF4=", - version = "v0.3.0", - ) - go_repository( - name = "com_google_cloud_go_gkeconnect", - importpath = "cloud.google.com/go/gkeconnect", - sum = "h1:zAcvDa04tTnGdu6TEZewaLN2tdMtUOJJ7fEceULjguA=", - version = "v0.6.0", - ) - go_repository( - name = "com_google_cloud_go_gkehub", - importpath = "cloud.google.com/go/gkehub", - sum = "h1:JTcTaYQRGsVm+qkah7WzHb6e9sf1C0laYdRPn9aN+vg=", - version = "v0.10.0", - ) - go_repository( - name = "com_google_cloud_go_gkemulticloud", - importpath = "cloud.google.com/go/gkemulticloud", - sum = "h1:8F1NhJj8ucNj7lK51UZMtAjSWTgP1zO18XF6vkfiPPU=", - version = "v0.4.0", - ) - go_repository( - name = "com_google_cloud_go_gsuiteaddons", - importpath = "cloud.google.com/go/gsuiteaddons", - sum = "h1:TGT2oGmO5q3VH6SjcrlgPUWI0njhYv4kywLm6jag0to=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_iam", - importpath = "cloud.google.com/go/iam", - sum = "h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk=", - version = "v0.8.0", - ) - go_repository( - name = "com_google_cloud_go_iap", - importpath = "cloud.google.com/go/iap", - sum = "h1:BGEXovwejOCt1zDk8hXq0bOhhRu9haXKWXXXp2B4wBM=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_ids", - importpath = "cloud.google.com/go/ids", - sum = "h1:LncHK4HHucb5Du310X8XH9/ICtMwZ2PCfK0ScjWiJoY=", - version = "v1.2.0", - ) - go_repository( - name = "com_google_cloud_go_iot", - importpath = "cloud.google.com/go/iot", - sum = "h1:Y9+oZT9jD4GUZzORXTU45XsnQrhxmDT+TFbPil6pRVQ=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_kms", - importpath = "cloud.google.com/go/kms", - sum = "h1:OWRZzrPmOZUzurjI2FBGtgY2mB1WaJkqhw6oIwSj0Yg=", - version = "v1.6.0", - ) - go_repository( - name = "com_google_cloud_go_language", - importpath = "cloud.google.com/go/language", - sum = "h1:3Wa+IUMamL4JH3Zd3cDZUHpwyqplTACt6UZKRD2eCL4=", - version = "v1.8.0", - ) - go_repository( - name = "com_google_cloud_go_lifesciences", - importpath = "cloud.google.com/go/lifesciences", - sum = "h1:tIqhivE2LMVYkX0BLgG7xL64oNpDaFFI7teunglt1tI=", - version = "v0.6.0", - ) - go_repository( - name = "com_google_cloud_go_logging", - importpath = "cloud.google.com/go/logging", - sum = "h1:ZBsZK+JG+oCDT+vaxwqF2egKNRjz8soXiS6Xv79benI=", - version = "v1.6.1", - ) go_repository( name = "com_google_cloud_go_longrunning", importpath = "cloud.google.com/go/longrunning", sum = "h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs=", version = "v0.3.0", ) - go_repository( - name = "com_google_cloud_go_managedidentities", - importpath = "cloud.google.com/go/managedidentities", - sum = "h1:3Kdajn6X25yWQFhFCErmKSYTSvkEd3chJROny//F1A0=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_maps", - importpath = "cloud.google.com/go/maps", - sum = "h1:kLReRbclTgJefw2fcCbdLPLhPj0U6UUWN10ldG8sdOU=", - version = "v0.1.0", - ) - go_repository( - name = "com_google_cloud_go_mediatranslation", - importpath = "cloud.google.com/go/mediatranslation", - sum = "h1:qAJzpxmEX+SeND10Y/4868L5wfZpo4Y3BIEnIieP4dk=", - version = "v0.6.0", - ) - go_repository( - name = "com_google_cloud_go_memcache", - importpath = "cloud.google.com/go/memcache", - sum = "h1:yLxUzJkZVSH2kPaHut7k+7sbIBFpvSh1LW9qjM2JDjA=", - version = "v1.7.0", - ) - go_repository( - name = "com_google_cloud_go_metastore", - importpath = "cloud.google.com/go/metastore", - sum = "h1:3KcShzqWdqxrDEXIBWpYJpOOrgpDj+HlBi07Grot49Y=", - version = "v1.8.0", - ) - go_repository( - name = "com_google_cloud_go_monitoring", - importpath = "cloud.google.com/go/monitoring", - sum = "h1:c9riaGSPQ4dUKWB+M1Fl0N+iLxstMbCktdEwYSPGDvA=", - version = "v1.8.0", - ) - go_repository( - name = "com_google_cloud_go_networkconnectivity", - importpath = "cloud.google.com/go/networkconnectivity", - sum = "h1:BVdIKaI68bihnXGdCVL89Jsg9kq2kg+II30fjVqo62E=", - version = "v1.7.0", - ) - go_repository( - name = "com_google_cloud_go_networkmanagement", - importpath = "cloud.google.com/go/networkmanagement", - sum = "h1:mDHA3CDW00imTvC5RW6aMGsD1bH+FtKwZm/52BxaiMg=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_networksecurity", - importpath = "cloud.google.com/go/networksecurity", - sum = "h1:qDEX/3sipg9dS5JYsAY+YvgTjPR63cozzAWop8oZS94=", - version = "v0.6.0", - ) - go_repository( - name = "com_google_cloud_go_notebooks", - importpath = "cloud.google.com/go/notebooks", - sum = "h1:AC8RPjNvel3ExgXjO1YOAz+teg9+j+89TNxa7pIZfww=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_optimization", - importpath = "cloud.google.com/go/optimization", - sum = "h1:7PxOq9VTT7TMib/6dMoWpMvWS2E4dJEvtYzjvBreaec=", - version = "v1.2.0", - ) - go_repository( - name = "com_google_cloud_go_orchestration", - importpath = "cloud.google.com/go/orchestration", - sum = "h1:39d6tqvNjd/wsSub1Bn4cEmrYcet5Ur6xpaN+SxOxtY=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_orgpolicy", - importpath = "cloud.google.com/go/orgpolicy", - sum = "h1:erF5PHqDZb6FeFrUHiYj2JK2BMhsk8CyAg4V4amJ3rE=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_osconfig", - importpath = "cloud.google.com/go/osconfig", - sum = "h1:NO0RouqCOM7M2S85Eal6urMSSipWwHU8evzwS+siqUI=", - version = "v1.10.0", - ) - go_repository( - name = "com_google_cloud_go_oslogin", - importpath = "cloud.google.com/go/oslogin", - sum = "h1:pKGDPfeZHDybtw48WsnVLjoIPMi9Kw62kUE5TXCLCN4=", - version = "v1.7.0", - ) - go_repository( - name = "com_google_cloud_go_phishingprotection", - importpath = "cloud.google.com/go/phishingprotection", - sum = "h1:OrwHLSRSZyaiOt3tnY33dsKSedxbMzsXvqB21okItNQ=", - version = "v0.6.0", - ) - go_repository( - name = "com_google_cloud_go_policytroubleshooter", - importpath = "cloud.google.com/go/policytroubleshooter", - sum = "h1:NQklJuOUoz1BPP+Epjw81COx7IISWslkZubz/1i0UN8=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_privatecatalog", - importpath = "cloud.google.com/go/privatecatalog", - sum = "h1:Vz86uiHCtNGm1DeC32HeG2VXmOq5JRYA3VRPf8ZEcSg=", - version = "v0.6.0", - ) go_repository( name = "com_google_cloud_go_pubsub", importpath = "cloud.google.com/go/pubsub", - sum = "h1:q+J/Nfr6Qx4RQeu3rJcnN48SNC0qzlYzSeqkPq93VHs=", - version = "v1.27.1", - ) - go_repository( - name = "com_google_cloud_go_pubsublite", - importpath = "cloud.google.com/go/pubsublite", - sum = "h1:iqrD8vp3giTb7hI1q4TQQGj77cj8zzgmMPsTZtLnprM=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_recaptchaenterprise_v2", - importpath = "cloud.google.com/go/recaptchaenterprise/v2", - sum = "h1:UqzFfb/WvhwXGDF1eQtdHLrmni+iByZXY4h3w9Kdyv8=", - version = "v2.5.0", - ) - go_repository( - name = "com_google_cloud_go_recommendationengine", - importpath = "cloud.google.com/go/recommendationengine", - sum = "h1:6w+WxPf2LmUEqX0YyvfCoYb8aBYOcbIV25Vg6R0FLGw=", - version = "v0.6.0", - ) - go_repository( - name = "com_google_cloud_go_recommender", - importpath = "cloud.google.com/go/recommender", - sum = "h1:9kMZQGeYfcOD/RtZfcNKGKtoex3DdoB4zRgYU/WaIwE=", - version = "v1.8.0", - ) - go_repository( - name = "com_google_cloud_go_redis", - importpath = "cloud.google.com/go/redis", - sum = "h1:/zTwwBKIAD2DEWTrXZp8WD9yD/gntReF/HkPssVYd0U=", - version = "v1.10.0", - ) - go_repository( - name = "com_google_cloud_go_resourcemanager", - importpath = "cloud.google.com/go/resourcemanager", - sum = "h1:NDao6CHMwEZIaNsdWy+tuvHaavNeGP06o1tgrR0kLvU=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_resourcesettings", - importpath = "cloud.google.com/go/resourcesettings", - sum = "h1:eTzOwB13WrfF0kuzG2ZXCfB3TLunSHBur4s+HFU6uSM=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_retail", - importpath = "cloud.google.com/go/retail", - sum = "h1:N9fa//ecFUOEPsW/6mJHfcapPV0wBSwIUwpVZB7MQ3o=", - version = "v1.11.0", - ) - go_repository( - name = "com_google_cloud_go_run", - importpath = "cloud.google.com/go/run", - sum = "h1:AWPuzU7Xtaj3Jf+QarDWIs6AJ5hM1VFQ+F6Q+VZ6OT4=", - version = "v0.3.0", - ) - go_repository( - name = "com_google_cloud_go_scheduler", - importpath = "cloud.google.com/go/scheduler", - sum = "h1:K/mxOewgHGeKuATUJNGylT75Mhtjmx1TOkKukATqMT8=", - version = "v1.7.0", - ) - go_repository( - name = "com_google_cloud_go_secretmanager", - importpath = "cloud.google.com/go/secretmanager", - sum = "h1:xE6uXljAC1kCR8iadt9+/blg1fvSbmenlsDN4fT9gqw=", - version = "v1.9.0", - ) - go_repository( - name = "com_google_cloud_go_security", - importpath = "cloud.google.com/go/security", - sum = "h1:KSKzzJMyUoMRQzcz7azIgqAUqxo7rmQ5rYvimMhikqg=", - version = "v1.10.0", - ) - go_repository( - name = "com_google_cloud_go_securitycenter", - importpath = "cloud.google.com/go/securitycenter", - sum = "h1:QTVtk/Reqnx2bVIZtJKm1+mpfmwRwymmNvlaFez7fQY=", - version = "v1.16.0", - ) - go_repository( - name = "com_google_cloud_go_servicecontrol", - importpath = "cloud.google.com/go/servicecontrol", - sum = "h1:ImIzbOu6y4jL6ob65I++QzvqgFaoAKgHOG+RU9/c4y8=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_servicedirectory", - importpath = "cloud.google.com/go/servicedirectory", - sum = "h1:f7M8IMcVzO3T425AqlZbP3yLzeipsBHtRza8vVFYMhQ=", - version = "v1.7.0", - ) - go_repository( - name = "com_google_cloud_go_servicemanagement", - importpath = "cloud.google.com/go/servicemanagement", - sum = "h1:TpkCO5M7dhKSy1bKUD9o/sSEW/U1Gtx7opA1fsiMx0c=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_serviceusage", - importpath = "cloud.google.com/go/serviceusage", - sum = "h1:b0EwJxPJLpavSljMQh0RcdHsUrr5DQ+Nelt/3BAs5ro=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_shell", - importpath = "cloud.google.com/go/shell", - sum = "h1:b1LFhFBgKsG252inyhtmsUUZwchqSz3WTvAIf3JFo4g=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_spanner", - importpath = "cloud.google.com/go/spanner", - sum = "h1:NvdTpRwf7DTegbfFdPjAWyD7bOVu0VeMqcvR9aCQCAc=", - version = "v1.41.0", - ) - go_repository( - name = "com_google_cloud_go_speech", - importpath = "cloud.google.com/go/speech", - sum = "h1:yK0ocnFH4Wsf0cMdUyndJQ/hPv02oTJOxzi6AgpBy4s=", - version = "v1.9.0", + sum = "h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=", + version = "v1.3.1", ) go_repository( name = "com_google_cloud_go_storage", @@ -1859,96 +1267,6 @@ def go_deps(): sum = "h1:6RRlFMv1omScs6iq2hfE3IvgE+l6RfJPampq8UZc5TU=", version = "v1.14.0", ) - go_repository( - name = "com_google_cloud_go_storagetransfer", - importpath = "cloud.google.com/go/storagetransfer", - sum = "h1:fUe3OydbbvHcAYp07xY+2UpH4AermGbmnm7qdEj3tGE=", - version = "v1.6.0", - ) - go_repository( - name = "com_google_cloud_go_talent", - importpath = "cloud.google.com/go/talent", - sum = "h1:MrekAGxLqAeAol4Sc0allOVqUGO8j+Iim8NMvpiD7tM=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_texttospeech", - importpath = "cloud.google.com/go/texttospeech", - sum = "h1:ccPiHgTewxgyAeCWgQWvZvrLmbfQSFABTMAfrSPLPyY=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_tpu", - importpath = "cloud.google.com/go/tpu", - sum = "h1:ztIdKoma1Xob2qm6QwNh4Xi9/e7N3IfvtwG5AcNsj1g=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_trace", - importpath = "cloud.google.com/go/trace", - sum = "h1:qO9eLn2esajC9sxpqp1YKX37nXC3L4BfGnPS0Cx9dYo=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_translate", - importpath = "cloud.google.com/go/translate", - sum = "h1:AOYOH3MspzJ/bH1YXzB+xTE8fMpn3mwhLjugwGXvMPI=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_video", - importpath = "cloud.google.com/go/video", - sum = "h1:ttlvO4J5c1VGq6FkHqWPD/aH6PfdxujHt+muTJlW1Zk=", - version = "v1.9.0", - ) - go_repository( - name = "com_google_cloud_go_videointelligence", - importpath = "cloud.google.com/go/videointelligence", - sum = "h1:RPFgVVXbI2b5vnrciZjtsUgpNKVtHO/WIyXUhEfuMhA=", - version = "v1.9.0", - ) - go_repository( - name = "com_google_cloud_go_vision_v2", - importpath = "cloud.google.com/go/vision/v2", - sum = "h1:TQHxRqvLMi19azwm3qYuDbEzZWmiKJNTpGbkNsfRCik=", - version = "v2.5.0", - ) - go_repository( - name = "com_google_cloud_go_vmmigration", - importpath = "cloud.google.com/go/vmmigration", - sum = "h1:A2Tl2ZmwMRpvEmhV2ibISY85fmQR+Y5w9a0PlRz5P3s=", - version = "v1.3.0", - ) - go_repository( - name = "com_google_cloud_go_vmwareengine", - importpath = "cloud.google.com/go/vmwareengine", - sum = "h1:JMPZaOT/gIUxVlTqSl/QQ32Y2k+r0stNeM1NSqhVP9o=", - version = "v0.1.0", - ) - go_repository( - name = "com_google_cloud_go_vpcaccess", - importpath = "cloud.google.com/go/vpcaccess", - sum = "h1:woHXXtnW8b9gLFdWO9HLPalAddBQ9V4LT+1vjKwR3W8=", - version = "v1.5.0", - ) - go_repository( - name = "com_google_cloud_go_webrisk", - importpath = "cloud.google.com/go/webrisk", - sum = "h1:ypSnpGlJnZSXbN9a13PDmAYvVekBLnGKxQ3Q9SMwnYY=", - version = "v1.7.0", - ) - go_repository( - name = "com_google_cloud_go_websecurityscanner", - importpath = "cloud.google.com/go/websecurityscanner", - sum = "h1:y7yIFg/h/mO+5Y5aCOtVAnpGUOgqCH5rXQ2Oc8Oq2+g=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_workflows", - importpath = "cloud.google.com/go/workflows", - sum = "h1:7Chpin9p50NTU8Tb7qk+I11U/IwVXmDhEoSsdccvInE=", - version = "v1.9.0", - ) go_repository( name = "com_lukechampine_uint128", importpath = "lukechampine.com/uint128", @@ -2066,14 +1384,34 @@ def go_deps(): go_repository( name = "org_golang_google_genproto", importpath = "google.golang.org/genproto", - sum = "h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=", - version = "v0.0.0-20230110181048-76db0878b65f", + sum = "h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g=", + version = "v0.0.0-20230803162519-f966b187b2e5", + ) + go_repository( + name = "org_golang_google_genproto_googleapis_api", + importpath = "google.golang.org/genproto/googleapis/api", + sum = "h1:m8v1xLLLzMe1m5P+gCTF8nJB9epwZQUBERm20Oy1poQ=", + version = "v0.0.0-20230525234035-dd9d682886f9", + ) + go_repository( + name = "org_golang_google_genproto_googleapis_rpc", + importpath = "google.golang.org/genproto/googleapis/rpc", + sum = "h1:lv6/DhyiFFGsmzxbsUUTOkN29II+zeWHxvT8Lpdxsv0=", + version = "v0.0.0-20230815205213-6bfd019c3878", ) go_repository( name = "org_golang_google_grpc", + # XXX(uniquefine): + # Starting with release v0.41.0 rules_go no longer includes the @go_googleapis repo. + # Instead all code code generated from protobufs for Google APIs will have to depend on + # @org_golang_google_genproto. As of v0.32.0 gazelle does not yet correctly resolve dependencies + # to this repository. Thus we have to manually add this here. + build_directives = [ + "gazelle:resolve go google.golang.org/genproto/googleapis/rpc/status @org_golang_google_genproto_googleapis_rpc//status", + ], importpath = "google.golang.org/grpc", - sum = "h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=", - version = "v1.53.0", + sum = "h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=", + version = "v1.57.0", ) go_repository( name = "org_golang_google_grpc_examples", @@ -2084,8 +1422,8 @@ def go_deps(): go_repository( name = "org_golang_google_protobuf", importpath = "google.golang.org/protobuf", - sum = "h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=", - version = "v1.28.1", + sum = "h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=", + version = "v1.31.0", ) go_repository( name = "org_golang_x_crypto", @@ -2138,8 +1476,8 @@ def go_deps(): go_repository( name = "org_golang_x_oauth2", importpath = "golang.org/x/oauth2", - sum = "h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M=", - version = "v0.4.0", + sum = "h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=", + version = "v0.7.0", ) go_repository( name = "org_golang_x_sync", diff --git a/licenses/data/com_github_quic_go_qtls_go1_19/LICENSE b/licenses/data/com_github_quic_go_qtls_go1_20/LICENSE similarity index 100% rename from licenses/data/com_github_quic_go_qtls_go1_19/LICENSE rename to licenses/data/com_github_quic_go_qtls_go1_20/LICENSE diff --git a/licenses/data/go_sdk/src/cmd/vendor/golang.org/x/crypto/LICENSE b/licenses/data/go_sdk/src/cmd/vendor/golang.org/x/crypto/LICENSE deleted file mode 100644 index 6a66aea5e..000000000 --- a/licenses/data/go_sdk/src/cmd/vendor/golang.org/x/crypto/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/licenses/data/go_googleapis/LICENSE b/licenses/data/org_golang_google_genproto_googleapis_rpc/LICENSE old mode 100755 new mode 100644 similarity index 99% rename from licenses/data/go_googleapis/LICENSE rename to licenses/data/org_golang_google_genproto_googleapis_rpc/LICENSE index 261eeb9e9..d64569567 --- a/licenses/data/go_googleapis/LICENSE +++ b/licenses/data/org_golang_google_genproto_googleapis_rpc/LICENSE @@ -1,3 +1,4 @@ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/nogo.json b/nogo.json index d87461c69..bad20152f 100644 --- a/nogo.json +++ b/nogo.json @@ -20,7 +20,8 @@ }, "copylocks": { "exclude_files": { - "/org_golang_google_protobuf/internal/impl/": "" + "/org_golang_google_protobuf/internal/impl/": "", + "gazelle/walk/config": "" } }, "nilness": { @@ -142,7 +143,8 @@ }, "lostcancel": { "exclude_files": { - "com_github_grpc_ecosystem_go_grpc_middleware/retry": "" + "com_github_grpc_ecosystem_go_grpc_middleware/retry": "", + "org_golang_x_tools": "" } }, "maincheck": { @@ -150,6 +152,9 @@ "/com_github_deepmap_oapi_codegen/": "", "/com_github_golang_mock/mockgen": "", "/org_golang_x_tools": "", + "gazelle/language/go/gen_std_package_list": "", + "gazelle/language/proto/gen/gen_known_imports": "", + "gazelle/cmd/gazelle/gazelle": "", "/com_github_bazelbuild_buildtools": "" } }, @@ -206,8 +211,8 @@ "org_golang_x_crypto/ed25519/internal/edwards25519": "", "com_github_vishvananda_netlink/nl": "", "com_github_deepmap_oapi_codegen/pkg/codegen": "", - "com_github_bazelbuild_buildtools": "", - "com_github_quic_go_quic_go/internal/wire/ack_frame.go": "" + "com_github_quic_go_quic_go": "", + "com_github_bazelbuild_buildtools": "" } } } diff --git a/pkg/private/serrors/testdata/error-list.log b/pkg/private/serrors/testdata/error-list.log index 0294f1681..7cff5bbf1 100644 --- a/pkg/private/serrors/testdata/error-list.log +++ b/pkg/private/serrors/testdata/error-list.log @@ -1 +1 @@ -{"err":[{"ctx1":"val1","msg":"test err","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:227","testing.tRunner src/testing/testing.go:1446","runtime.goexit src/runtime/asm_amd64.s:1594"]},{"msg":"test err2","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:228","testing.tRunner src/testing/testing.go:1446","runtime.goexit src/runtime/asm_amd64.s:1594"]}],"level":"info","msg":"Failed to do thing"} \ No newline at end of file +{"err":[{"ctx1":"val1","msg":"test err","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:227","testing.tRunner src/testing/testing.go:1595","runtime.goexit src/runtime/asm_amd64.s:1650"]},{"msg":"test err2","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:228","testing.tRunner src/testing/testing.go:1595","runtime.goexit src/runtime/asm_amd64.s:1650"]}],"level":"info","msg":"Failed to do thing"} \ No newline at end of file diff --git a/pkg/private/serrors/testdata/error-with-context.log b/pkg/private/serrors/testdata/error-with-context.log index ac9182eff..807fc51f6 100644 --- a/pkg/private/serrors/testdata/error-with-context.log +++ b/pkg/private/serrors/testdata/error-with-context.log @@ -1 +1 @@ -{"err":{"msg":{"msg":"simple err","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:222","testing.tRunner src/testing/testing.go:1446","runtime.goexit src/runtime/asm_amd64.s:1594"]},"someCtx":"someValue"},"level":"info","msg":"Failed to do thing"} \ No newline at end of file +{"err":{"msg":{"msg":"simple err","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:222","testing.tRunner src/testing/testing.go:1595","runtime.goexit src/runtime/asm_amd64.s:1650"]},"someCtx":"someValue"},"level":"info","msg":"Failed to do thing"} \ No newline at end of file diff --git a/pkg/private/serrors/testdata/new-with-context.log b/pkg/private/serrors/testdata/new-with-context.log index 6a6e614ff..0779fccc1 100644 --- a/pkg/private/serrors/testdata/new-with-context.log +++ b/pkg/private/serrors/testdata/new-with-context.log @@ -1 +1 @@ -{"err":{"k0":"v0","k1":1,"msg":"err msg","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:191","testing.tRunner src/testing/testing.go:1446","runtime.goexit src/runtime/asm_amd64.s:1594"]},"level":"info","msg":"Failed to do thing"} \ No newline at end of file +{"err":{"k0":"v0","k1":1,"msg":"err msg","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:191","testing.tRunner src/testing/testing.go:1595","runtime.goexit src/runtime/asm_amd64.s:1650"]},"level":"info","msg":"Failed to do thing"} \ No newline at end of file diff --git a/pkg/private/serrors/testdata/wrapped-error.log b/pkg/private/serrors/testdata/wrapped-error.log index ee7896f3b..ccf49307c 100644 --- a/pkg/private/serrors/testdata/wrapped-error.log +++ b/pkg/private/serrors/testdata/wrapped-error.log @@ -1 +1 @@ -{"err":{"cause":{"msg":"msg cause","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:215","testing.tRunner src/testing/testing.go:1446","runtime.goexit src/runtime/asm_amd64.s:1594"]},"k0":"v0","k1":1,"msg":{"msg":"msg error","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:214","testing.tRunner src/testing/testing.go:1446","runtime.goexit src/runtime/asm_amd64.s:1594"]}},"level":"info","msg":"Failed to do thing"} \ No newline at end of file +{"err":{"cause":{"msg":"msg cause","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:215","testing.tRunner src/testing/testing.go:1595","runtime.goexit src/runtime/asm_amd64.s:1650"]},"k0":"v0","k1":1,"msg":{"msg":"msg error","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:214","testing.tRunner src/testing/testing.go:1595","runtime.goexit src/runtime/asm_amd64.s:1650"]}},"level":"info","msg":"Failed to do thing"} \ No newline at end of file diff --git a/pkg/private/serrors/testdata/wrapped-string.log b/pkg/private/serrors/testdata/wrapped-string.log index e2e61a3db..dc7cd3baf 100644 --- a/pkg/private/serrors/testdata/wrapped-string.log +++ b/pkg/private/serrors/testdata/wrapped-string.log @@ -1 +1 @@ -{"err":{"cause":{"msg":"msg cause","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:197","testing.tRunner src/testing/testing.go:1446","runtime.goexit src/runtime/asm_amd64.s:1594"]},"k0":"v0","k1":1,"msg":"msg error"},"level":"info","msg":"Failed to do thing"} \ No newline at end of file +{"err":{"cause":{"msg":"msg cause","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:197","testing.tRunner src/testing/testing.go:1595","runtime.goexit src/runtime/asm_amd64.s:1650"]},"k0":"v0","k1":1,"msg":"msg error"},"level":"info","msg":"Failed to do thing"} \ No newline at end of file diff --git a/pkg/private/serrors/testdata/wrapped-with-string.log b/pkg/private/serrors/testdata/wrapped-with-string.log index 48e04ab3a..aba98048b 100644 --- a/pkg/private/serrors/testdata/wrapped-with-string.log +++ b/pkg/private/serrors/testdata/wrapped-with-string.log @@ -1 +1 @@ -{"err":{"cause":{"cause_ctx_key":"cause_ctx_val","msg":"msg cause","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:206","testing.tRunner src/testing/testing.go:1446","runtime.goexit src/runtime/asm_amd64.s:1594"]},"k0":"v0","k1":1,"msg":"msg error"},"level":"info","msg":"Failed to do thing"} \ No newline at end of file +{"err":{"cause":{"cause_ctx_key":"cause_ctx_val","msg":"msg cause","stacktrace":["pkg/private/serrors/go_default_test_test.TestEncoding pkg/private/serrors/errors_test.go:206","testing.tRunner src/testing/testing.go:1595","runtime.goexit src/runtime/asm_amd64.s:1650"]},"k0":"v0","k1":1,"msg":"msg error"},"level":"info","msg":"Failed to do thing"} \ No newline at end of file diff --git a/pkg/proto/control_plane/cppki.pb.go b/pkg/proto/control_plane/cppki.pb.go index 88b44141f..6f56be0c2 100644 --- a/pkg/proto/control_plane/cppki.pb.go +++ b/pkg/proto/control_plane/cppki.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/control_plane/v1/cppki.proto diff --git a/pkg/proto/control_plane/drkey.pb.go b/pkg/proto/control_plane/drkey.pb.go index 8899da472..594607898 100644 --- a/pkg/proto/control_plane/drkey.pb.go +++ b/pkg/proto/control_plane/drkey.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/control_plane/v1/drkey.proto diff --git a/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go b/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go index 712ee9983..0f5c3051d 100755 --- a/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go +++ b/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/control_plane/experimental/v1/seg_detached_extensions.proto diff --git a/pkg/proto/control_plane/renewal.pb.go b/pkg/proto/control_plane/renewal.pb.go index f328cd366..ed3359b4c 100644 --- a/pkg/proto/control_plane/renewal.pb.go +++ b/pkg/proto/control_plane/renewal.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/control_plane/v1/renewal.proto diff --git a/pkg/proto/control_plane/seg.pb.go b/pkg/proto/control_plane/seg.pb.go index 2fa2fe964..36f549223 100644 --- a/pkg/proto/control_plane/seg.pb.go +++ b/pkg/proto/control_plane/seg.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/control_plane/v1/seg.proto diff --git a/pkg/proto/control_plane/seg_extensions.pb.go b/pkg/proto/control_plane/seg_extensions.pb.go index 738ba0b8d..565f0e5bd 100644 --- a/pkg/proto/control_plane/seg_extensions.pb.go +++ b/pkg/proto/control_plane/seg_extensions.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/control_plane/v1/seg_extensions.proto diff --git a/pkg/proto/control_plane/svc_resolution.pb.go b/pkg/proto/control_plane/svc_resolution.pb.go index 25fb87c87..781251817 100644 --- a/pkg/proto/control_plane/svc_resolution.pb.go +++ b/pkg/proto/control_plane/svc_resolution.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/control_plane/v1/svc_resolution.proto diff --git a/pkg/proto/crypto/signed.pb.go b/pkg/proto/crypto/signed.pb.go index 287f30e7c..bc09b3824 100644 --- a/pkg/proto/crypto/signed.pb.go +++ b/pkg/proto/crypto/signed.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/crypto/v1/signed.proto diff --git a/pkg/proto/daemon/daemon.pb.go b/pkg/proto/daemon/daemon.pb.go index 152d30c25..24bddc037 100644 --- a/pkg/proto/daemon/daemon.pb.go +++ b/pkg/proto/daemon/daemon.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/daemon/v1/daemon.proto diff --git a/pkg/proto/discovery/discovery.pb.go b/pkg/proto/discovery/discovery.pb.go index d1d8920f2..704dab49b 100644 --- a/pkg/proto/discovery/discovery.pb.go +++ b/pkg/proto/discovery/discovery.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/discovery/v1/discovery.proto diff --git a/pkg/proto/drkey/drkey.pb.go b/pkg/proto/drkey/drkey.pb.go index 80b7d25f3..0c7bc5ebf 100644 --- a/pkg/proto/drkey/drkey.pb.go +++ b/pkg/proto/drkey/drkey.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/drkey/v1/drkey.proto diff --git a/pkg/proto/gateway/control.pb.go b/pkg/proto/gateway/control.pb.go index 41895e811..952a5a067 100644 --- a/pkg/proto/gateway/control.pb.go +++ b/pkg/proto/gateway/control.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/gateway/v1/control.proto diff --git a/pkg/proto/gateway/prefix.pb.go b/pkg/proto/gateway/prefix.pb.go index 96157978d..ce4a8d0e7 100644 --- a/pkg/proto/gateway/prefix.pb.go +++ b/pkg/proto/gateway/prefix.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/gateway/v1/prefix.proto diff --git a/pkg/proto/hidden_segment/hidden_segment.pb.go b/pkg/proto/hidden_segment/hidden_segment.pb.go index c87c0376f..5303dc9df 100644 --- a/pkg/proto/hidden_segment/hidden_segment.pb.go +++ b/pkg/proto/hidden_segment/hidden_segment.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.30.0 // protoc v3.15.3 // source: proto/hidden_segment/v1/hidden_segment.proto diff --git a/pkg/scrypto/signed/BUILD.bazel b/pkg/scrypto/signed/BUILD.bazel index e08f1bd5e..d1180cd19 100644 --- a/pkg/scrypto/signed/BUILD.bazel +++ b/pkg/scrypto/signed/BUILD.bazel @@ -12,7 +12,7 @@ go_library( "//pkg/private/serrors:go_default_library", "//pkg/proto/crypto:go_default_library", "@com_github_golang_protobuf//ptypes:go_default_library_gen", - "@io_bazel_rules_go//proto/wkt:timestamp_go_proto", + "@com_github_golang_protobuf//ptypes/timestamp", "@org_golang_google_protobuf//proto:go_default_library", ], ) diff --git a/pkg/snet/squic/net.go b/pkg/snet/squic/net.go index e20d21e45..199464639 100644 --- a/pkg/snet/squic/net.go +++ b/pkg/snet/squic/net.go @@ -316,7 +316,7 @@ func (c *acceptingConn) RemoteAddr() net.Addr { } func (c *acceptingConn) ConnectionState() tls.ConnectionState { - return c.session.ConnectionState().TLS.ConnectionState + return c.session.ConnectionState().TLS } func (c *acceptingConn) Close() error { @@ -473,7 +473,7 @@ func (c *acceptedConn) RemoteAddr() net.Addr { } func (c *acceptedConn) ConnectionState() tls.ConnectionState { - return c.session.ConnectionState().TLS.ConnectionState + return c.session.ConnectionState().TLS } func (c *acceptedConn) Close() error { diff --git a/pkg/snet/squic/net_test.go b/pkg/snet/squic/net_test.go index a75036503..700a6f618 100644 --- a/pkg/snet/squic/net_test.go +++ b/pkg/snet/squic/net_test.go @@ -81,12 +81,14 @@ func TestAcceptLoopParallelism(t *testing.T) { }), ) if err != nil { + t.Log(err) return false } defer conn.Close() client := cppb.NewTrustMaterialServiceClient(conn) if _, err := client.TRC(ctx, &cppb.TRCRequest{}); err != nil { + t.Log(err) return false } return true diff --git a/private/trust/grpc/BUILD.bazel b/private/trust/grpc/BUILD.bazel index c2b9b2474..a306375b1 100644 --- a/private/trust/grpc/BUILD.bazel +++ b/private/trust/grpc/BUILD.bazel @@ -21,8 +21,8 @@ go_library( "//private/tracing:go_default_library", "//private/trust:go_default_library", "//private/trust/internal/metrics:go_default_library", + "@com_github_golang_protobuf//ptypes/timestamp", "@com_github_opentracing_opentracing_go//:go_default_library", - "@io_bazel_rules_go//proto/wkt:timestamp_go_proto", ], ) From d176fc029ca351b82e7d14f89a8e9a9551f2f4b6 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Mon, 18 Sep 2023 13:31:41 +0200 Subject: [PATCH 052/255] scion/ping: wait for send go routine to terminate (#4392) Wait for the ping sender go routine to terminate before we return the stats. With bad luck, the receiver go routine receives all the replies before the sender go routine has terminated. Because only the sender go routine increments the stats.Sent count, we end up with wrong stats that claim more packets were received then sent. The race condition is that `WriteTo` in the last `pinger.send` succeeds, but then the writer go-routine is not scheduled to increment the `stats.Sent` counter before these stats are returned from `pinger.Ping`. --- scion/ping/ping.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scion/ping/ping.go b/scion/ping/ping.go index c332bce42..4efea528d 100644 --- a/scion/ping/ping.go +++ b/scion/ping/ping.go @@ -20,6 +20,7 @@ import ( "encoding/binary" "math/rand" "net" + "sync" "time" "github.com/scionproto/scion/pkg/addr" @@ -178,8 +179,12 @@ func (p *pinger) Ping(ctx context.Context, remote *snet.UDPAddr) (Stats, error) p.drain(ctx) }() + var wg sync.WaitGroup + wg.Add(1) + go func() { defer log.HandlePanic() + defer wg.Done() for i := uint16(0); i < p.attempts; i++ { if err := p.send(remote); err != nil { errSend <- serrors.WrapStr("sending", err) @@ -210,6 +215,7 @@ func (p *pinger) Ping(ctx context.Context, remote *snet.UDPAddr) (Stats, error) p.receive(reply) } } + wg.Wait() return p.stats, nil } From 010baef685bfa057d2dde33351f03f7ac036c211 Mon Sep 17 00:00:00 2001 From: Markus Legner Date: Mon, 18 Sep 2023 14:45:28 +0200 Subject: [PATCH 053/255] docs: update link in CONTRIBUTING.md (#4393) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d01e624d..0277a8a3e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ # Contribution Guide The Contribution Guide for the SCION project can be found -[here](https://docs.scion.org/en/latest/contribute.html). +[here](https://docs.scion.org/en/latest/dev/contribute.html). From 468618633db29e36835923b24fcb7dcdf93c261d Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Tue, 19 Sep 2023 15:28:09 +0200 Subject: [PATCH 054/255] ci: upload binaries as artifacts (#4391) Upload binaries built in the build step as build artifacts. Add a buildkite "annotation" to give quick access to these archive with these binaries. Inlcudes some cleanup around the uploading of artifacts and related hooks. Now only the handling of the bazel-remote and go-module-proxy is left in the pre-command/pre-exit hooks. The rest is moved into step-specific metahook-hooks. This includes collecting the test outputs artifacts -- this is kept as archives instead of individual files, just because the number of individual test output files seems somewhat overwhelming in the buildkite UI. --- .buildkite/cleanup-leftovers.sh | 11 +++++ .buildkite/hooks/pre-artifact | 76 --------------------------------- .buildkite/hooks/pre-command | 11 ++--- .buildkite/hooks/pre-exit | 21 +-------- .buildkite/pipeline.yml | 44 +++++++++++++------ .buildkite/pipeline_lib.sh | 7 ++- README.md | 4 +- 7 files changed, 57 insertions(+), 117 deletions(-) create mode 100755 .buildkite/cleanup-leftovers.sh delete mode 100755 .buildkite/hooks/pre-artifact diff --git a/.buildkite/cleanup-leftovers.sh b/.buildkite/cleanup-leftovers.sh new file mode 100755 index 000000000..cc1bb05b3 --- /dev/null +++ b/.buildkite/cleanup-leftovers.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +echo "~~~ Cleaning up any leftovers" +cntrs="$(docker ps -aq | grep -v -f <(docker ps -q --filter "name=go-module-proxy" --filter "name=bazel-remote-cache"))" +[ -n "$cntrs" ] && { echo "Remove leftover containers..."; docker rm -f $cntrs; } +echo "Remove leftover networks" +docker network prune -f +echo "Remove leftover volumes" +docker volume prune -f + +rm -rf bazel-testlogs logs/* traces gen gen-cache /tmp/test-artifacts test-out.tar.gz diff --git a/.buildkite/hooks/pre-artifact b/.buildkite/hooks/pre-artifact deleted file mode 100755 index 231320d4e..000000000 --- a/.buildkite/hooks/pre-artifact +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash - -set -eo pipefail - -# Attempt to do clean docker topology shutdown. -# This lets applications flush the logs to avoid cutting them off. -if [ -f "gen/scion-dc.yml" ]; then - # This hook is global, therefore we need to disable fail on error because - # not all docker-compose tests are following the pattern - # COMPOSE_PROJECT_NAME=scion, COMPOSE_FILE=gen/scion-dc.yml - # and logs in stdout. - set +e - docker-compose -f gen/scion-dc.yml -p scion stop - - docker-compose -f gen/scion-dc.yml -p scion logs --no-color > logs/scion-dc.log - - for s in $(docker-compose -f gen/scion-dc.yml -p scion ps --services); do - cat logs/scion-dc.log | grep $s| cut -f2 -d"|" > logs/${s#"scion_"}.log - done - - docker-compose -f gen/scion-dc.yml -p scion down -v - - # a subset of tests are using testgen and they do a collect log and dc stop - # on their own. Therefore the above code produces empty files that are confusing. - # Given the limitation of buildkite that the hook is global we just cleanup - # the empty files. - find . -type f -empty -delete - - set -e -fi - -# Now we build the artifact name next, for this we first need TARGET and BUILD, -# see below. -# -# For PRs the target is the pull request, otherwise it is the branch. -TARGET="$BUILDKITE_PULL_REQUEST" -if [ "$BUILDKITE_PULL_REQUEST" == "false" ]; then - TARGET="$BUILDKITE_BRANCH" -fi -TARGET="${TARGET//\//_}" -echo "\$TARGET=$TARGET" - -# For nightly builds instead of the build number print nightly and the date. -BUILD="build-${BUILDKITE_BUILD_NUMBER}" -[ -n "$NIGHTLY" ] && BUILD=nightly-"$(date +%s)" -echo "\$BUILD=$BUILD" - -ARTIFACTS="buildkite.${BUILDKITE_ORGANIZATION_SLUG}.${TARGET}.${BUILD}.${BUILDKITE_STEP_KEY:-unset}.${BUILDKITE_JOB_ID}" -mkdir -p "artifacts/$ARTIFACTS" artifacts.out - -function save { - if [ -d "$1" ]; then - echo Found artifacts: "$1" - cp -R "$1" "artifacts/$ARTIFACTS" - fi -} - -# Also store remote cache logs -cache_ctr=$(docker ps -aq -f "name=bazel-remote-cache") -if [ ! -z "$cache_ctr" ]; then - mkdir -p logs/docker - docker logs bazel-remote-cache > logs/docker/bazel-remote-cache.log -fi - -save "bazel-testlogs" -save "outputs" -save "logs" -save "traces" -save "gen" -save "gen-cache" -save "/tmp/test-artifacts" - -tar chaf "artifacts.out/$ARTIFACTS.tar.gz" -C artifacts "$ARTIFACTS" -rm -rf artifacts - -echo "Output tar= artifacts.out/$ARTIFACTS.tar.gz" diff --git a/.buildkite/hooks/pre-command b/.buildkite/hooks/pre-command index f43be60ae..0650d3644 100755 --- a/.buildkite/hooks/pre-command +++ b/.buildkite/hooks/pre-command @@ -11,15 +11,12 @@ printenv PATH # Install build tools on first job for this runner. .buildkite/provision-agent.sh -# Clean up left-overs from previous run -PRE_COMMAND_SETUP=true . .buildkite/hooks/pre-exit - set -euo pipefail -echo "--- Increase receive network buffer size" +echo "~~~ Increase receive network buffer size" sudo sysctl -w net.core.rmem_max=1048576 -echo "--- Setting up bazel environment" +echo "~~~ Setting up bazel environment" if [ -z ${BAZEL_REMOTE_S3_ACCESS_KEY_ID+x} ]; then echo "S3 env not set, not starting bazel remote proxy" @@ -41,12 +38,12 @@ else fi echo "test --test_env CI" >> $HOME/.bazelrc -echo "--- Starting bazel remote cache proxy" +echo "~~~ Starting bazel remote cache proxy" # Start bazel remote cache proxy for S3 # Note that S3 keys are injected by buildkite, see # https://buildkite.com/docs/pipelines/secrets#storing-secrets-with-the-elastic-ci-stack-for-aws docker-compose -f .buildkite/hooks/bazel-remote.yml -p bazel_remote up -d -echo "--- Starting go module proxy" +echo "~~~ Starting go module proxy" docker-compose -f .buildkite/hooks/go-module-proxy.yml -p athens up -d diff --git a/.buildkite/hooks/pre-exit b/.buildkite/hooks/pre-exit index 1b85eab6d..ba1758cc1 100644 --- a/.buildkite/hooks/pre-exit +++ b/.buildkite/hooks/pre-exit @@ -1,8 +1,7 @@ #!/bin/bash - -if [ -f ".buildkite/hooks/bazel-remote.yml" -a -z "$PRE_COMMAND_SETUP" ]; then - echo "--- Uploading bazel-remote and go-module-proxy logs/metrics" +if [ -f ".buildkite/hooks/bazel-remote.yml" ]; then + echo "~~~ Uploading bazel-remote and go-module-proxy logs/metrics" curl http://localhost:8080/metrics > bazel-remote-cache.metrics docker logs bazel-remote-cache &> bazel-remote-cache.log @@ -11,19 +10,3 @@ if [ -f ".buildkite/hooks/bazel-remote.yml" -a -z "$PRE_COMMAND_SETUP" ]; then buildkite-agent artifact upload "bazel-remote-cache.*;go-module-proxy.*" fi - -echo "--- Cleaning up the topology" - -./scion.sh topo_clean - -echo "--- Cleaning up docker containers/networks/volumes" -cntrs="$(docker ps -aq | grep -v -f <(docker ps -q --filter "name=go-module-proxy" --filter "name=bazel-remote-cache"))" -[ -n "$cntrs" ] && { echo "Remove leftover containers..."; docker rm -f $cntrs; } - -echo "Remove leftover networks" -docker network prune -f -echo "Remove leftover volumes" -docker volume prune -f - -echo "--- Cleaning up logs and artifacts" -rm -rf bazel-testlogs logs/* traces gen gen-cache /tmp/test-artifacts diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index aac4913f2..65ed0a203 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -3,9 +3,20 @@ env: steps: - label: "Build :bazel:" command: - - bazel build --verbose_failures --announce_rc //:all + - bazel build --verbose_failures --announce_rc //:scion //:scion-ci - bazel run --verbose_failures //docker:prod //docker:test key: build + artifact_paths: + - "bazel-bin/scion.tar" + - "bazel-bin/scion-ci.tar" + plugins: + - scionproto/metahook#v0.3.0: + post-artifact: | + cat << EOF | buildkite-agent annotate --style "info" + #### Build outputs + - SCION binaries + - SCION test tools and utilities + EOF retry: &automatic-retry automatic: - exit_status: -1 # Agent was lost @@ -16,8 +27,11 @@ steps: command: - bazel test --config=race --config=unit_all key: unit_tests + plugins: + - scionproto/metahook#v0.3.0: + pre-artifact: tar -chaf bazel-testlogs.tar.gz bazel-testlogs artifact_paths: - - "artifacts.out/**/*" + - bazel-testlogs.tar.gz retry: *automatic-retry timeout_in_minutes: 20 - label: "Lint :bash:" @@ -69,14 +83,20 @@ steps: - tools/await-connectivity - ./bin/scion_integration || ( echo "^^^ +++" && false ) - ./bin/end2end_integration || ( echo "^^^ +++" && false ) - plugins: &shutdown-scion-post-command + plugins: &scion-run-hooks - scionproto/metahook#v0.3.0: + pre-command: .buildkite/cleanup-leftovers.sh post-command: | - echo "--- Shutting down SCION topology" + echo "~~~ Shutting down SCION topology" ./scion.sh stop - echo "SCION topology successfully shut down" - artifact_paths: - - "artifacts.out/**/*" + pre-artifact: | + if [ -f "gen/scion-dc.yml" ]; then + tools/dc collect_logs scion logs/ + fi + tar -chaf test-out.tar.gz $(ls -d logs traces gen gen-cache) # ls -d to filter missing directories + pre-exit: .buildkite/cleanup-leftovers.sh + artifact_paths: &scion-run-artifact-paths + - test-out.tar.gz timeout_in_minutes: 15 key: e2e_integration_tests_v2 retry: *automatic-retry @@ -90,9 +110,8 @@ steps: - tools/await-connectivity - ./bin/end2end_integration || ( echo "^^^ +++" && false ) - ./tools/integration/revocation_test.sh - plugins: *shutdown-scion-post-command - artifact_paths: - - "artifacts.out/**/*" + plugins: *scion-run-hooks + artifact_paths: *scion-run-artifact-paths timeout_in_minutes: 15 key: e2e_revocation_test_v2 retry: *automatic-retry @@ -106,9 +125,8 @@ steps: - tools/await-connectivity - echo "--- run tests" - ./bin/end2end_integration -d || ( echo "^^^ +++" && false ) - plugins: *shutdown-scion-post-command - artifact_paths: - - "artifacts.out/**/*" + plugins: *scion-run-hooks + artifact_paths: *scion-run-artifact-paths timeout_in_minutes: 15 key: docker_integration_e2e_default retry: *automatic-retry diff --git a/.buildkite/pipeline_lib.sh b/.buildkite/pipeline_lib.sh index 7f1de5016..ced606e47 100644 --- a/.buildkite/pipeline_lib.sh +++ b/.buildkite/pipeline_lib.sh @@ -44,8 +44,13 @@ gen_bazel_test_steps() { echo " command:" echo " - bazel test --test_output=streamed $test $args $cache" echo " key: \"${name////_}\"" + echo " plugins:" + echo " - scionproto/metahook#v0.3.0:" + echo " pre-command: .buildkite/cleanup-leftovers.sh" + echo " pre-artifact: tar -chaf bazel-testlogs.tar.gz bazel-testlogs" + echo " pre-exit: .buildkite/cleanup-leftovers.sh" echo " artifact_paths:" - echo " - \"artifacts.out/**/*\"" + echo " - \"bazel-testlogs.tar.gz\"" echo " timeout_in_minutes: 20" echo " retry:" echo " automatic:" diff --git a/README.md b/README.md index e98ad5d61..0c3016ad6 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Slack chat](https://img.shields.io/badge/chat%20on-slack-blue?logo=slack)](https://scionproto.slack.com) [![ReadTheDocs](https://img.shields.io/badge/doc-reference-blue?version=latest&style=flat&label=docs&logo=read-the-docs&logoColor=white)](https://docs.scion.org/en/latest) [![Documentation](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/github.com/scionproto/scion) -[![Build Status](https://badge.buildkite.com/e7ca347d947c23883ad7c3a4d091c2df5ae7feb52b238d29a1.svg?branch=master)](https://buildkite.com/scionproto/scion) +[![Nightly Build](https://badge.buildkite.com/b70b65b38a75eb8724f41a6f1203c9327cfb767f07a0c1934e.svg)](https://buildkite.com/scionproto/scion-nightly/builds/latest) [![Go Report Card](https://goreportcard.com/badge/github.com/scionproto/scion)](https://goreportcard.com/report/github.com/scionproto/scion) [![GitHub issues](https://img.shields.io/github/issues/scionproto/scion/help%20wanted.svg?label=help%20wanted&color=purple)](https://github.com/scionproto/scion/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) [![GitHub issues](https://img.shields.io/github/issues/scionproto/scion/good%20first%20issue.svg?label=good%20first%20issue&color=purple)](https://github.com/scionproto/scion/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) @@ -31,6 +31,8 @@ To find out how to work with SCION, please visit our [documentation site](https://docs.scion.org/en/latest/dev/setup.html) for instructions on how to install build dependencies, build and run SCION. +Pre-built binaries for x86-64 Linux are available from the [latest nightly build](https://buildkite.com/scionproto/scion-nightly/builds/latest). + ## Contributing Interested in contribution to the SCION project? Please visit our From e80afbfc43a40acf1264559c571804a986fa51aa Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Fri, 22 Sep 2023 11:19:20 +0200 Subject: [PATCH 055/255] protocol: implement peering links (#4390) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement support for peering links in the router. This is the first time that peering links are supported since the "new" SCION header, and small fixes in the segment combinator and some of the tools were needed. The main implementation was done by @benthor in #4299. This #4390 contains @jiceatscion's finalization pass of this, in particular adding tests. Closes #4299. Closes #4093. --------- Co-authored-by: Thorben Krüger --- acceptance/README.md | 16 +- control/beaconing/extender.go | 24 +- pkg/slayers/path/scion/base.go | 10 +- private/path/combinator/graph.go | 35 ++- private/topology/json/json.go | 11 +- private/topology/topology.go | 4 + router/control/conf.go | 5 +- router/dataplane.go | 120 ++++++-- router/dataplane_test.go | 410 +++++++++++++++++++++++--- scion/traceroute/traceroute.go | 5 +- tools/braccept/cases/BUILD.bazel | 3 + tools/braccept/cases/child_to_peer.go | 196 ++++++++++++ tools/braccept/cases/doc.go | 13 +- tools/braccept/cases/peer_to_child.go | 194 ++++++++++++ tools/braccept/main.go | 2 + tools/topology/topo.py | 18 +- topology/peering-test-multi.topo | 41 +++ topology/peering-test.topo | 40 +++ 18 files changed, 1059 insertions(+), 88 deletions(-) create mode 100644 tools/braccept/cases/child_to_peer.go create mode 100644 tools/braccept/cases/peer_to_child.go create mode 100644 topology/peering-test-multi.topo create mode 100644 topology/peering-test.topo diff --git a/acceptance/README.md b/acceptance/README.md index cab20b6f3..49b8b435a 100644 --- a/acceptance/README.md +++ b/acceptance/README.md @@ -3,6 +3,9 @@ This directory contains a set of integration tests. Each test is defined as a bazel test target, with tags `integration` and `exclusive`. +Some integration tests use code outside this directory. For example, the +`router_multi` acceptance test cases and main executable are in `tools/braccept`. + ## Basic Commands To run all integration tests which include the acceptance tests, execute one of @@ -18,6 +21,7 @@ Run a subset of the tests by specifying a different list of targets: ```bash bazel test --config=integration //acceptance/cert_renewal:all //acceptance/trc_update/... +bazel test --config=integration //acceptance/router_multi:all --cache_test_results=no ``` The following the flags to bazel test can be helpful when running individual tests: @@ -27,8 +31,8 @@ The following the flags to bazel test can be helpful when running individual tes ## Manual Testing -Some of the tests are defined using a common framework, defined in the -bazel rules `topogen_test` and `raw_test`. +Some of the tests are defined using a common framework, implemented by the +bazel rules `topogen_test` and `raw_test` (in [raw.bzl](acceptance/common/raw.bzl)). These test cases allow more fine grained interaction. ```bash @@ -41,5 +45,13 @@ bazel run //:_run bazel run //:_teardown ``` +For example: + +```bash +bazel run //acceptance/router_multi:test_bfd_setup +bazel run //acceptance/router_multi:test_bfd_run +bazel run //acceptance/router_multi:test_bfd_teardown +``` + See [common/README](common/README.md) for more information about the internal structure of these tests. diff --git a/control/beaconing/extender.go b/control/beaconing/extender.go index 2c02c5e35..7e5fe00a4 100644 --- a/control/beaconing/extender.go +++ b/control/beaconing/extender.go @@ -62,7 +62,7 @@ type DefaultExtender struct { EPIC bool } -// Extend extends the beacon with hop fields of the old format. +// Extend extends the beacon with hop fields. func (s *DefaultExtender) Extend( ctx context.Context, pseg *seg.PathSegment, @@ -85,11 +85,25 @@ func (s *DefaultExtender) Extend( } ts := pseg.Info.Timestamp - hopEntry, epicHopMac, err := s.createHopEntry(ingress, egress, ts, extractBeta(pseg)) + hopBeta := extractBeta(pseg) + hopEntry, epicHopMac, err := s.createHopEntry(ingress, egress, ts, hopBeta) if err != nil { return serrors.WrapStr("creating hop entry", err) } - peerBeta := extractBeta(pseg) ^ binary.BigEndian.Uint16(hopEntry.HopField.MAC[:2]) + + // The peer hop fields chain to the main hop field, just like any child hop field. + // The effect of this is that when a peer hop field is used in a path, both the + // peer hop field and its child are validated using the same SegID accumlator value: + // that originally intended for the child. + // + // The corrolary is that one cannot validate a hop field's MAC by looking at the + // parent hop field MAC when the parent is a peering hop field. This is ok: that + // is never done that way, it is always done by validating against the SegID + // accumulator supplied by the previous router on the forwarding path. The + // forwarding code takes care of not updating that accumulator when a peering hop + // is traversed. + + peerBeta := hopBeta ^ binary.BigEndian.Uint16(hopEntry.HopField.MAC[:2]) peerEntries, epicPeerMacs, err := s.createPeerEntries(egress, peers, ts, peerBeta) if err != nil { return err @@ -268,6 +282,10 @@ func (s *DefaultExtender) createHopF(ingress, egress uint16, ts time.Time, }, fullMAC[path.MacLen:] } +// extractBeta computes the beta value that must be used for the next hop to be +// added at the end of the segment. +// FIXME(jice): keeping an accumulator would be just as easy to do as it is during +// forwarding. What's the benefit of re-calculating the whole chain every time? func extractBeta(pseg *seg.PathSegment) uint16 { beta := pseg.Info.SegmentID for _, entry := range pseg.ASEntries { diff --git a/pkg/slayers/path/scion/base.go b/pkg/slayers/path/scion/base.go index dc6a9fc66..b2a781223 100644 --- a/pkg/slayers/path/scion/base.go +++ b/pkg/slayers/path/scion/base.go @@ -76,7 +76,9 @@ func (s *Base) IncPath() error { } if int(s.PathMeta.CurrHF) >= s.NumHops-1 { s.PathMeta.CurrHF = uint8(s.NumHops - 1) - return serrors.New("path already at end") + return serrors.New("path already at end", + "curr_hf", s.PathMeta.CurrHF, + "num_hops", s.NumHops) } s.PathMeta.CurrHF++ // Update CurrINF @@ -84,7 +86,11 @@ func (s *Base) IncPath() error { return nil } -// IsXover returns whether we are at a crossover point. +// IsXover returns whether we are at a crossover point. This includes +// all segment switches, even over a peering link. Note that handling +// of a regular segment switch and handling of a segment switch over a +// peering link are fundamentally different. To distinguish the two, +// you will need to extract the information from the info field. func (s *Base) IsXover() bool { return s.PathMeta.CurrHF+1 < uint8(s.NumHops) && s.PathMeta.CurrINF != s.infIndexForHF(s.PathMeta.CurrHF+1) diff --git a/private/path/combinator/graph.go b/private/path/combinator/graph.go index 6b90e4cba..eb092ca70 100644 --- a/private/path/combinator/graph.go +++ b/private/path/combinator/graph.go @@ -239,7 +239,11 @@ func (g *dmg) GetPaths(src, dst vertex) pathSolutionList { } // inputSegment is a local representation of a path segment that includes the -// segment's type. +// segment's type. The type (up down or core) indicates the role that this +// segment holds in a path solution. That is, in which order the hops would +// be used for building an actual forwarding path (e.g. from the end in the +// case of an UP segment). However, the hops within the referred PathSegment +// *always* remain in construction order. type inputSegment struct { *seg.PathSegment Type proto.PathSegType @@ -316,7 +320,11 @@ func (solution *pathSolution) Path() Path { var pathASEntries []seg.ASEntry // ASEntries that on the path, eventually in path order. var epicSegAuths [][]byte - // Go through each ASEntry, starting from the last one, until we + // Segments are in construction order, regardless of whether they're + // up or down segments. We traverse them FROM THE END. So, in reverse + // forwarding order for down segments and in forwarding order for + // up segments. + // We go through each ASEntry, starting from the last one until we // find a shortcut (which can be 0, meaning the end of the segment). asEntries := solEdge.segment.ASEntries for asEntryIdx := len(asEntries) - 1; asEntryIdx >= solEdge.edge.Shortcut; asEntryIdx-- { @@ -378,6 +386,9 @@ func (solution *pathSolution) Path() Path { } } + // Put the hops in forwarding order. Needed for down segments + // since we collected hops from the end, just like for up + // segments. if solEdge.segment.Type == proto.PathSegType_down { reverseHops(hops) reverseIntfs(intfs) @@ -487,15 +498,30 @@ func reverseEpicAuths(s [][]byte) { } func calculateBeta(se *solutionEdge) uint16 { + + // If this is a peer hop, we need to set beta[i] = beta[i+1]. That is, the SegID + // accumulator must correspond to the next (in construction order) hop. + // + // This is because this peering hop has a MAC that chains to its non-peering + // counterpart, the same as what the next hop (in construction order) chains to. + // So both this and the next hop are to be validated from the same SegID + // accumulator value: the one for the *next* hop, calculated on the regular + // non-peering segment. + // + // Note that, when traversing peer hops, the SegID accumulator is left untouched for the + // next router on the path to use. + var index int if se.segment.IsDownSeg() { index = se.edge.Shortcut - // If this is a peer, we need to set beta i+1. if se.edge.Peer != 0 { index++ } } else { index = len(se.segment.ASEntries) - 1 + if index == se.edge.Shortcut && se.edge.Peer != 0 { + index++ + } } beta := se.segment.Info.SegmentID for i := 0; i < index; i++ { @@ -586,7 +612,8 @@ func validNextSeg(currSeg, nextSeg *inputSegment) bool { } // segment is a helper that represents a path segment during the conversion -// from the graph solution to the raw forwarding information. +// from the graph solution to the raw forwarding information. The hops should +// be in forwarding order. type segment struct { InfoField path.InfoField HopFields []path.HopField diff --git a/private/topology/json/json.go b/private/topology/json/json.go index 08e7cf333..d07de43a0 100644 --- a/private/topology/json/json.go +++ b/private/topology/json/json.go @@ -107,11 +107,12 @@ type GatewayInfo struct { // BRInterface contains the information for an data-plane BR socket that is external (i.e., facing // the neighboring AS). type BRInterface struct { - Underlay Underlay `json:"underlay,omitempty"` - IA string `json:"isd_as"` - LinkTo string `json:"link_to"` - MTU int `json:"mtu"` - BFD *BFD `json:"bfd,omitempty"` + Underlay Underlay `json:"underlay,omitempty"` + IA string `json:"isd_as"` + LinkTo string `json:"link_to"` + MTU int `json:"mtu"` + BFD *BFD `json:"bfd,omitempty"` + RemoteIFID common.IFIDType `json:"remote_interface_id,omitempty"` } // Underlay is the underlay information for a BR interface. diff --git a/private/topology/topology.go b/private/topology/topology.go index 56bc02321..d2d3f5856 100644 --- a/private/topology/topology.go +++ b/private/topology/topology.go @@ -243,6 +243,10 @@ func (t *RWTopology) populateBR(raw *jsontopo.Topology) error { return err } ifinfo.LinkType = LinkTypeFromString(rawIntf.LinkTo) + if ifinfo.LinkType == Peer { + ifinfo.RemoteIFID = rawIntf.RemoteIFID + } + if err = ifinfo.CheckLinks(t.IsCore, name); err != nil { return err } diff --git a/router/control/conf.go b/router/control/conf.go index 1e68e892c..d5cf15a67 100644 --- a/router/control/conf.go +++ b/router/control/conf.go @@ -50,10 +50,11 @@ type LinkInfo struct { MTU int } -// LinkEnd represents on end of a link. +// LinkEnd represents one end of a link. type LinkEnd struct { IA addr.IA Addr *net.UDPAddr + IFID common.IFIDType } type ObservableDataplane interface { @@ -174,10 +175,12 @@ func confExternalInterfaces(dp Dataplane, cfg *Config) error { Local: LinkEnd{ IA: cfg.IA, Addr: snet.CopyUDPAddr(iface.Local), + IFID: iface.ID, }, Remote: LinkEnd{ IA: iface.IA, Addr: snet.CopyUDPAddr(iface.Remote), + IFID: iface.RemoteIFID, }, Instance: iface.BRName, BFD: WithDefaults(BFD(iface.BFD)), diff --git a/router/dataplane.go b/router/dataplane.go index 609ba3358..d47348f9c 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -98,6 +98,7 @@ type DataPlane struct { external map[uint16]BatchConn linkTypes map[uint16]topology.LinkType neighborIAs map[uint16]addr.IA + peerInterfaces map[uint16]uint16 internal BatchConn internalIP netip.Addr internalNextHops map[uint16]*net.UDPAddr @@ -130,6 +131,11 @@ var ( noBFDSessionFound = serrors.New("no BFD sessions was found") noBFDSessionConfigured = serrors.New("no BFD sessions have been configured") errBFDDisabled = serrors.New("BFD is disabled") + errPeeringEmptySeg0 = serrors.New("zero-length segment[0] in peering path") + errPeeringEmptySeg1 = serrors.New("zero-length segment[1] in peering path") + errPeeringNonemptySeg2 = serrors.New("non-zero-length segment[2] in peering path") + errShortPacket = serrors.New("Packet is too short") + errBFDSessionDown = serrors.New("bfd session down") // zeroBuffer will be used to reset the Authenticator option in the // scionPacketProcessor.OptAuth zeroBuffer = make([]byte, 16) @@ -281,6 +287,24 @@ func (d *DataPlane) AddLinkType(ifID uint16, linkTo topology.LinkType) error { return nil } +// AddRemotePeer adds the remote peering interface ID for local +// interface ID. If the link type for the given ID is already set to +// a different type, this method will return an error. This can only +// be called on a not yet running dataplane. +func (d *DataPlane) AddRemotePeer(local, remote uint16) error { + if t, ok := d.linkTypes[local]; ok && t != topology.Peer { + return serrors.WithCtx(unsupportedPathType, "type", t) + } + if _, exists := d.peerInterfaces[local]; exists { + return serrors.WithCtx(alreadySet, "local_interface", local) + } + if d.peerInterfaces == nil { + d.peerInterfaces = make(map[uint16]uint16) + } + d.peerInterfaces[local] = remote + return nil +} + // AddExternalInterfaceBFD adds the inter AS connection BFD session. func (d *DataPlane) AddExternalInterfaceBFD(ifID uint16, conn BatchConn, src, dst control.LinkEnd, cfg control.BFD) error { @@ -621,13 +645,13 @@ func computeProcID(data []byte, numProcRoutines int, randomValue []byte, flowIDBuffer []byte, hasher hash.Hash32) (uint32, error) { if len(data) < slayers.CmnHdrLen { - return 0, serrors.New("Packet is too short") + return 0, errShortPacket } dstHostAddrLen := slayers.AddrType(data[9] >> 4 & 0xf).Length() srcHostAddrLen := slayers.AddrType(data[9] & 0xf).Length() addrHdrLen := 2*addr.IABytes + srcHostAddrLen + dstHostAddrLen if len(data) < slayers.CmnHdrLen+addrHdrLen { - return 0, serrors.New("Packet is too short") + return 0, errShortPacket } copy(flowIDBuffer[0:3], data[1:4]) flowIDBuffer[0] &= 0xF // the left 4 bits don't belong to the flowID @@ -819,7 +843,8 @@ func (p *scionPacketProcessor) reset() error { p.path = nil p.hopField = path.HopField{} p.infoField = path.InfoField{} - p.segmentChange = false + p.effectiveXover = false + p.peering = false if err := p.buffer.Clear(); err != nil { return serrors.WrapStr("Failed to clear buffer", err) } @@ -1010,8 +1035,10 @@ type scionPacketProcessor struct { hopField path.HopField // infoField is the current infoField field, is updated during processing. infoField path.InfoField - // segmentChange indicates if the path segment was changed during processing. - segmentChange bool + // effectiveXover indicates if a cross-over segment change was done during processing. + effectiveXover bool + // peering indicates that the hop field being processed is a peering hop field. + peering bool // cachedMac contains the full 16 bytes of the MAC. Will be set during processing. // For a hop performing an Xover, it is the MAC corresponding to the down segment. @@ -1081,6 +1108,32 @@ func (p *scionPacketProcessor) parsePath() (processResult, error) { return processResult{}, nil } +func (p *scionPacketProcessor) determinePeer() (processResult, error) { + if !p.infoField.Peer { + return processResult{}, nil + } + + if p.path.PathMeta.SegLen[0] == 0 { + return processResult{}, errPeeringEmptySeg0 + } + if p.path.PathMeta.SegLen[1] == 0 { + return processResult{}, errPeeringEmptySeg1 + + } + if p.path.PathMeta.SegLen[2] != 0 { + return processResult{}, errPeeringNonemptySeg2 + } + + // The peer hop fields are the last hop field on the first path + // segment (at SegLen[0] - 1) and the first hop field of the second + // path segment (at SegLen[0]). The below check applies only + // because we already know this is a well-formed peering path. + currHF := p.path.PathMeta.CurrHF + segLen := p.path.PathMeta.SegLen[0] + p.peering = currHF == segLen-1 || currHF == segLen + return processResult{}, nil +} + func (p *scionPacketProcessor) validateHopExpiry() (processResult, error) { expiration := util.SecsToTime(p.infoField.Timestamp). Add(path.ExpTimeToDuration(p.hopField.ExpTime)) @@ -1199,9 +1252,11 @@ func (p *scionPacketProcessor) validateEgressID() (processResult, error) { } ingress, egress := p.d.linkTypes[p.ingressID], p.d.linkTypes[pktEgressID] - if !p.segmentChange { + if !p.effectiveXover { // Check that the interface pair is valid within a single segment. // No check required if the packet is received from an internal interface. + // This case applies to peering hops as a peering hop isn't an effective + // cross-over (eventhough it is a segment change). switch { case p.ingressID == 0: return processResult{}, nil @@ -1211,6 +1266,10 @@ func (p *scionPacketProcessor) validateEgressID() (processResult, error) { return processResult{}, nil case ingress == topology.Parent && egress == topology.Child: return processResult{}, nil + case ingress == topology.Child && egress == topology.Peer: + return processResult{}, nil + case ingress == topology.Peer && egress == topology.Child: + return processResult{}, nil default: // malicious return p.packSCMP( slayers.SCMPTypeParameterProblem, @@ -1222,6 +1281,9 @@ func (p *scionPacketProcessor) validateEgressID() (processResult, error) { } // Check that the interface pair is valid on a segment switch. // Having a segment change received from the internal interface is never valid. + // We should never see a peering link traversal either. If that happens + // treat it as a routing error (not sure if that can happen without an internal + // error, though). switch { case ingress == topology.Core && egress == topology.Child: return processResult{}, nil @@ -1242,9 +1304,8 @@ func (p *scionPacketProcessor) validateEgressID() (processResult, error) { func (p *scionPacketProcessor) updateNonConsDirIngressSegID() error { // against construction dir the ingress router updates the SegID, ifID == 0 // means this comes from this AS itself, so nothing has to be done. - // TODO(lukedirtwalker): For packets destined to peer links this shouldn't - // be updated. - if !p.infoField.ConsDir && p.ingressID != 0 { + // For packets destined to peer links this shouldn't be updated. + if !p.infoField.ConsDir && p.ingressID != 0 && !p.peering { p.infoField.UpdateSegID(p.hopField.Mac) if err := p.path.SetInfoField(p.infoField, int(p.path.PathMeta.CurrINF)); err != nil { return serrors.WrapStr("update info field", err) @@ -1270,12 +1331,14 @@ func (p *scionPacketProcessor) verifyCurrentMAC() (processResult, error) { slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidHopFieldMAC, &slayers.SCMPParameterProblem{Pointer: p.currentHopPointer()}, - serrors.New("MAC verification failed", "expected", fmt.Sprintf( - "%x", fullMac[:path.MacLen]), + serrors.New("MAC verification failed", + "expected", fmt.Sprintf("%x", fullMac[:path.MacLen]), "actual", fmt.Sprintf("%x", p.hopField.Mac[:path.MacLen]), "cons_dir", p.infoField.ConsDir, - "if_id", p.ingressID, "curr_inf", p.path.PathMeta.CurrINF, - "curr_hf", p.path.PathMeta.CurrHF, "seg_id", p.infoField.SegID), + "if_id", p.ingressID, + "curr_inf", p.path.PathMeta.CurrINF, + "curr_hf", p.path.PathMeta.CurrHF, + "seg_id", p.infoField.SegID), ) } // Add the full MAC to the SCION packet processor, @@ -1300,9 +1363,12 @@ func (p *scionPacketProcessor) resolveInbound() (*net.UDPAddr, processResult, er } func (p *scionPacketProcessor) processEgress() error { - // we are the egress router and if we go in construction direction we - // need to update the SegID. - if p.infoField.ConsDir { + // We are the egress router and if we go in construction direction we + // need to update the SegID (unless we are effecting a peering hop). + // When we're at a peering hop, the SegID for this hop and for the next + // are one and the same, both hops chain to the same parent. So do not + // update SegID. + if p.infoField.ConsDir && !p.peering { p.infoField.UpdateSegID(p.hopField.Mac) if err := p.path.SetInfoField(p.infoField, int(p.path.PathMeta.CurrINF)); err != nil { // TODO parameter problem invalid path @@ -1317,7 +1383,7 @@ func (p *scionPacketProcessor) processEgress() error { } func (p *scionPacketProcessor) doXover() (processResult, error) { - p.segmentChange = true + p.effectiveXover = true if err := p.path.IncPath(); err != nil { // TODO parameter problem invalid path return processResult{}, serrors.WrapStr("incrementing path", err) @@ -1337,7 +1403,7 @@ func (p *scionPacketProcessor) doXover() (processResult, error) { func (p *scionPacketProcessor) ingressInterface() uint16 { info := p.infoField hop := p.hopField - if p.path.IsFirstHopAfterXover() { + if !p.peering && p.path.IsFirstHopAfterXover() { var err error info, err = p.path.GetInfoField(int(p.path.PathMeta.CurrINF) - 1) if err != nil { // cannot be out of range @@ -1378,7 +1444,7 @@ func (p *scionPacketProcessor) validateEgressUp() (processResult, error) { Egress: uint64(egressID), } } - return p.packSCMP(typ, 0, scmpP, serrors.New("bfd session down")) + return p.packSCMP(typ, 0, scmpP, errBFDSessionDown) } } return processResult{}, nil @@ -1475,10 +1541,12 @@ func (p *scionPacketProcessor) validatePktLen() (processResult, error) { } func (p *scionPacketProcessor) process() (processResult, error) { - if r, err := p.parsePath(); err != nil { return r, err } + if r, err := p.determinePeer(); err != nil { + return r, err + } if r, err := p.validateHopExpiry(); err != nil { return r, err } @@ -1514,10 +1582,14 @@ func (p *scionPacketProcessor) process() (processResult, error) { // Outbound: pkts leaving the local IA. // BRTransit: pkts leaving from the same BR different interface. - if p.path.IsXover() { + if p.path.IsXover() && !p.peering { + // An effective cross-over is a change of segment other than at + // a peering hop. if r, err := p.doXover(); err != nil { return r, err } + // doXover() has changed the current segment and hop field. + // We need to validate the new hop field. if r, err := p.validateHopExpiry(); err != nil { return r, serrors.WithCtx(err, "info", "after xover") } @@ -1819,7 +1891,9 @@ func (p *scionPacketProcessor) prepareSCMP( revPath := revPathTmp.(*scion.Decoded) // Revert potential path segment switches that were done during processing. - if revPath.IsXover() { + if revPath.IsXover() && !p.peering { + // An effective cross-over is a change of segment other than at + // a peering hop. if err := revPath.IncPath(); err != nil { return nil, serrors.Wrap(cannotRoute, err, "details", "reverting cross over for SCMP") } @@ -1829,7 +1903,7 @@ func (p *scionPacketProcessor) prepareSCMP( _, external := p.d.external[p.ingressID] if external { infoField := &revPath.InfoFields[revPath.PathMeta.CurrINF] - if infoField.ConsDir { + if infoField.ConsDir && !p.peering { hopField := revPath.HopFields[revPath.PathMeta.CurrHF] infoField.UpdateSegID(hopField.Mac) } diff --git a/router/dataplane_test.go b/router/dataplane_test.go index 1eb6b6d1d..c83bc2701 100644 --- a/router/dataplane_test.go +++ b/router/dataplane_test.go @@ -570,15 +570,17 @@ func TestProcessPkt(t *testing.T) { defer ctrl.Finish() key := []byte("testkey_xxxxxxxx") + otherKey := []byte("testkey_yyyyyyyy") now := time.Now() epicTS, err := libepic.CreateTimestamp(now, now) require.NoError(t, err) testCases := map[string]struct { - mockMsg func(bool) *ipv4.Message - prepareDP func(*gomock.Controller) *router.DataPlane - srcInterface uint16 - assertFunc assert.ErrorAssertionFunc + mockMsg func(bool) *ipv4.Message + prepareDP func(*gomock.Controller) *router.DataPlane + srcInterface uint16 + egressInterface uint16 + assertFunc assert.ErrorAssertionFunc }{ "inbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -604,8 +606,9 @@ func TestProcessPkt(t *testing.T) { } return ret }, - srcInterface: 1, - assertFunc: assert.NoError, + srcInterface: 1, + egressInterface: 0, + assertFunc: assert.NoError, }, "outbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -638,8 +641,9 @@ func TestProcessPkt(t *testing.T) { ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil return ret }, - srcInterface: 0, - assertFunc: assert.NoError, + srcInterface: 0, + egressInterface: 1, + assertFunc: assert.NoError, }, "brtransit": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -672,8 +676,9 @@ func TestProcessPkt(t *testing.T) { ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil return ret }, - srcInterface: 1, - assertFunc: assert.NoError, + srcInterface: 1, + egressInterface: 2, + assertFunc: assert.NoError, }, "brtransit non consdir": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -706,8 +711,320 @@ func TestProcessPkt(t *testing.T) { ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil return ret }, - srcInterface: 1, - assertFunc: assert.NoError, + srcInterface: 1, + egressInterface: 2, + assertFunc: assert.NoError, + }, + "brtransit peering consdir": { + prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { + return router.NewDP( + map[uint16]router.BatchConn{ + uint16(2): mock_router.NewMockBatchConn(ctrl), + }, + map[uint16]topology.LinkType{ + 1: topology.Peer, + 2: topology.Child, + }, + nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + }, + mockMsg: func(afterProcessing bool) *ipv4.Message { + // Story: the packet just left segment 0 which ends at + // (peering) hop 0 and is landing on segment 1 which + // begins at (peering) hop 1. We do not care what hop 0 + // looks like. The forwarding code is looking at hop 1 and + // should leave the message in shape to be processed at hop 2. + spkt, _ := prepBaseMsg(now) + dpath := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 1, + CurrINF: 1, + SegLen: [3]uint8{1, 2, 0}, + }, + NumINF: 2, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + // up seg + {SegID: 0x111, ConsDir: true, Timestamp: util.TimeToSecs(now), Peer: true}, + // core seg + {SegID: 0x222, ConsDir: true, Timestamp: util.TimeToSecs(now), Peer: true}, + }, + HopFields: []path.HopField{ + {ConsIngress: 31, ConsEgress: 30}, + {ConsIngress: 1, ConsEgress: 2}, + {ConsIngress: 40, ConsEgress: 41}, + }, + } + + // Make obvious the unusual aspect of the path: two + // hopfield MACs (1 and 2) derive from the same SegID + // accumulator value. However, the forwarding code isn't + // supposed to even look at the second one. The SegID + // accumulator value can be anything (it comes from the + // parent hop of HF[1] in the original beaconned segment, + // which is not in the path). So, we use one from an + // info field because computeMAC makes that easy. + dpath.HopFields[1].Mac = computeMAC( + t, key, dpath.InfoFields[1], dpath.HopFields[1]) + dpath.HopFields[2].Mac = computeMAC( + t, otherKey, dpath.InfoFields[1], dpath.HopFields[2]) + if !afterProcessing { + return toMsg(t, spkt, dpath) + } + _ = dpath.IncPath() + + // ... The SegID accumulator wasn't updated from HF[1], + // it is still the same. That is the key behavior. + + ret := toMsg(t, spkt, dpath) + ret.Addr = nil + ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil + return ret + }, + srcInterface: 1, // from peering link + egressInterface: 2, + assertFunc: assert.NoError, + }, + "brtransit peering non consdir": { + prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { + return router.NewDP( + map[uint16]router.BatchConn{ + uint16(1): mock_router.NewMockBatchConn(ctrl), + }, + map[uint16]topology.LinkType{ + 1: topology.Peer, + 2: topology.Child, + }, + nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + }, + mockMsg: func(afterProcessing bool) *ipv4.Message { + // Story: the packet lands on the last (peering) hop of + // segment 0. After processing, the packet is ready to + // be processed by the first (peering) hop of segment 1. + spkt, _ := prepBaseMsg(now) + dpath := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 1, + CurrINF: 0, + SegLen: [3]uint8{2, 1, 0}, + }, + NumINF: 2, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + // up seg + {SegID: 0x111, ConsDir: false, Timestamp: util.TimeToSecs(now), Peer: true}, + // down seg + {SegID: 0x222, ConsDir: true, Timestamp: util.TimeToSecs(now), Peer: true}, + }, + HopFields: []path.HopField{ + {ConsIngress: 31, ConsEgress: 30}, + {ConsIngress: 1, ConsEgress: 2}, + {ConsIngress: 40, ConsEgress: 41}, + }, + } + + // Make obvious the unusual aspect of the path: two + // hopfield MACs (0 and 1) derive from the same SegID + // accumulator value. However, the forwarding code isn't + // supposed to even look at the first one. The SegID + // accumulator value can be anything (it comes from the + // parent hop of HF[1] in the original beaconned segment, + // which is not in the path). So, we use one from an + // info field because computeMAC makes that easy. + dpath.HopFields[0].Mac = computeMAC( + t, otherKey, dpath.InfoFields[0], dpath.HopFields[0]) + dpath.HopFields[1].Mac = computeMAC( + t, key, dpath.InfoFields[0], dpath.HopFields[1]) + + // We're going against construction order, so the accumulator + // value is that of the previous hop in traversal order. The + // story starts with the packet arriving at hop 1, so the + // accumulator value must match hop field 0. In this case, + // it is identical to that for hop field 1, which we made + // identical to the original SegID. So, we're all set. + if !afterProcessing { + return toMsg(t, spkt, dpath) + } + + _ = dpath.IncPath() + + // The SegID should not get updated on arrival. If it is, then MAC validation + // of HF1 will fail. Otherwise, this isn't visible because we changed segment. + + ret := toMsg(t, spkt, dpath) + ret.Addr = nil + ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil + return ret + }, + srcInterface: 2, // from child link + egressInterface: 1, + assertFunc: assert.NoError, + }, + "peering consdir downstream": { + // Similar to previous test case but looking at what + // happens on the next hop. + prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { + return router.NewDP( + map[uint16]router.BatchConn{ + uint16(2): mock_router.NewMockBatchConn(ctrl), + }, + map[uint16]topology.LinkType{ + 1: topology.Peer, + 2: topology.Child, + }, + nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + }, + mockMsg: func(afterProcessing bool) *ipv4.Message { + // Story: the packet just left hop 1 (the first hop + // of peering down segment 1) and is processed at hop 2 + // which is not a peering hop. + spkt, _ := prepBaseMsg(now) + dpath := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 2, + CurrINF: 1, + SegLen: [3]uint8{1, 3, 0}, + }, + NumINF: 2, + NumHops: 4, + }, + InfoFields: []path.InfoField{ + // up seg + {SegID: 0x111, ConsDir: true, Timestamp: util.TimeToSecs(now), Peer: true}, + // core seg + {SegID: 0x222, ConsDir: true, Timestamp: util.TimeToSecs(now), Peer: true}, + }, + HopFields: []path.HopField{ + {ConsIngress: 31, ConsEgress: 30}, + {ConsIngress: 40, ConsEgress: 41}, + {ConsIngress: 1, ConsEgress: 2}, + {ConsIngress: 50, ConsEgress: 51}, + // There has to be a 4th hop to make + // the 3rd router agree that the packet + // is not at destination yet. + }, + } + + // Make obvious the unusual aspect of the path: two + // hopfield MACs (1 and 2) derive from the same SegID + // accumulator value. The router shouldn't need to + // know this or do anything special. The SegID + // accumulator value can be anything (it comes from the + // parent hop of HF[1] in the original beaconned segment, + // which is not in the path). So, we use one from an + // info field because computeMAC makes that easy. + dpath.HopFields[1].Mac = computeMAC( + t, otherKey, dpath.InfoFields[1], dpath.HopFields[1]) + dpath.HopFields[2].Mac = computeMAC( + t, key, dpath.InfoFields[1], dpath.HopFields[2]) + if !afterProcessing { + // The SegID we provide is that of HF[2] which happens to be SEG[1]'s SegID, + // so, already set. + return toMsg(t, spkt, dpath) + } + _ = dpath.IncPath() + + // ... The SegID accumulator should have been updated. + dpath.InfoFields[1].UpdateSegID(dpath.HopFields[2].Mac) + + ret := toMsg(t, spkt, dpath) + ret.Addr = nil + ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil + return ret + }, + srcInterface: 1, + egressInterface: 2, + assertFunc: assert.NoError, + }, + "peering non consdir upstream": { + prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { + return router.NewDP( + map[uint16]router.BatchConn{ + uint16(1): mock_router.NewMockBatchConn(ctrl), + }, + map[uint16]topology.LinkType{ + 1: topology.Peer, + 2: topology.Child, + }, + nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + }, + mockMsg: func(afterProcessing bool) *ipv4.Message { + // Story: the packet lands on the second (non-peering) hop of + // segment 0 (a peering segment). After processing, the packet + // is ready to be processed by the third (peering) hop of segment 0. + spkt, _ := prepBaseMsg(now) + dpath := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 1, + CurrINF: 0, + SegLen: [3]uint8{3, 1, 0}, + }, + NumINF: 2, + NumHops: 4, + }, + InfoFields: []path.InfoField{ + // up seg + {SegID: 0x111, ConsDir: false, Timestamp: util.TimeToSecs(now), Peer: true}, + // down seg + {SegID: 0x222, ConsDir: true, Timestamp: util.TimeToSecs(now), Peer: true}, + }, + HopFields: []path.HopField{ + {ConsIngress: 31, ConsEgress: 30}, + {ConsIngress: 1, ConsEgress: 2}, + {ConsIngress: 40, ConsEgress: 41}, + {ConsIngress: 50, ConsEgress: 51}, + // The second segment (4th hop) has to be + // there but the packet isn't processed + // at that hop for this test. + }, + } + + // Make obvious the unusual aspect of the path: two + // hopfield MACs (1 and 2) derive from the same SegID + // accumulator value. The SegID accumulator value can + // be anything (it comes from the parent hop of HF[1] + // in the original beaconned segment, which is not in + // the path). So, we use one from an info field because + // computeMAC makes that easy. + dpath.HopFields[1].Mac = computeMAC( + t, key, dpath.InfoFields[0], dpath.HopFields[1]) + dpath.HopFields[2].Mac = computeMAC( + t, otherKey, dpath.InfoFields[0], dpath.HopFields[2]) + + if !afterProcessing { + // We're going against construction order, so the + // before-processing accumulator value is that of + // the previous hop in traversal order. The story + // starts with the packet arriving at hop 1, so the + // accumulator value must match hop field 0, which + // derives from hop field[1]. HopField[0]'s MAC is + // not checked during this test. + dpath.InfoFields[0].UpdateSegID(dpath.HopFields[1].Mac) + + return toMsg(t, spkt, dpath) + } + + _ = dpath.IncPath() + + // After-processing, the SegID should have been updated + // (on ingress) to be that of HF[1], which happens to be + // the Segment's SegID. That is what we already have as + // we only change it in the before-processing version + // of the packet. + + ret := toMsg(t, spkt, dpath) + ret.Addr = nil + ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil + return ret + }, + srcInterface: 2, // from child link + egressInterface: 1, + assertFunc: assert.NoError, }, "astransit direct": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -736,8 +1053,9 @@ func TestProcessPkt(t *testing.T) { } return ret }, - srcInterface: 1, - assertFunc: assert.NoError, + srcInterface: 1, + egressInterface: 0, + assertFunc: assert.NoError, }, "astransit xover": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -788,8 +1106,9 @@ func TestProcessPkt(t *testing.T) { ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil return ret }, - srcInterface: 51, - assertFunc: assert.NoError, + srcInterface: 51, + egressInterface: 0, + assertFunc: assert.NoError, }, "svc": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -823,8 +1142,9 @@ func TestProcessPkt(t *testing.T) { } return ret }, - srcInterface: 1, - assertFunc: assert.NoError, + srcInterface: 1, + egressInterface: 0, + assertFunc: assert.NoError, }, "svc nobackend": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -846,8 +1166,9 @@ func TestProcessPkt(t *testing.T) { ret := toMsg(t, spkt, dpath) return ret }, - srcInterface: 1, - assertFunc: assertIsSCMPError(slayers.SCMPTypeDestinationUnreachable, 0), + srcInterface: 1, + egressInterface: 0, + assertFunc: assertIsSCMPError(slayers.SCMPTypeDestinationUnreachable, 0), }, "svc invalid": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -869,8 +1190,9 @@ func TestProcessPkt(t *testing.T) { ret := toMsg(t, spkt, dpath) return ret }, - srcInterface: 1, - assertFunc: assertIsSCMPError(slayers.SCMPTypeDestinationUnreachable, 0), + srcInterface: 1, + egressInterface: 0, + assertFunc: assertIsSCMPError(slayers.SCMPTypeDestinationUnreachable, 0), }, "onehop inbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -931,8 +1253,9 @@ func TestProcessPkt(t *testing.T) { ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil return ret }, - srcInterface: 1, - assertFunc: assert.NoError, + srcInterface: 1, + egressInterface: 0, + assertFunc: assert.NoError, }, "onehop inbound invalid src": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -967,8 +1290,9 @@ func TestProcessPkt(t *testing.T) { } return toMsg(t, spkt, dpath) }, - srcInterface: 1, - assertFunc: assert.Error, + srcInterface: 1, + egressInterface: 21, + assertFunc: assert.Error, }, "reversed onehop outbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -1026,8 +1350,9 @@ func TestProcessPkt(t *testing.T) { ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil return ret }, - srcInterface: 0, - assertFunc: assert.NoError, + srcInterface: 0, + egressInterface: 1, + assertFunc: assert.NoError, }, "onehop outbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -1072,8 +1397,9 @@ func TestProcessPkt(t *testing.T) { ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil return ret }, - srcInterface: 0, - assertFunc: assert.NoError, + srcInterface: 0, + egressInterface: 2, + assertFunc: assert.NoError, }, "invalid dest": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -1094,7 +1420,8 @@ func TestProcessPkt(t *testing.T) { ret := toMsg(t, spkt, dpath) return ret }, - srcInterface: 1, + srcInterface: 1, + egressInterface: 0, assertFunc: assertIsSCMPError( slayers.SCMPTypeParameterProblem, slayers.SCMPCodeInvalidDestinationAddress, @@ -1112,8 +1439,9 @@ func TestProcessPkt(t *testing.T) { prepareEpicCrypto(t, spkt, epicpath, dpath, key) return toIP(t, spkt, epicpath, afterProcessing) }, - srcInterface: 1, - assertFunc: assert.NoError, + srcInterface: 1, + egressInterface: 0, + assertFunc: assert.NoError, }, "epic malformed path": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -1128,8 +1456,9 @@ func TestProcessPkt(t *testing.T) { // Wrong path type return toIP(t, spkt, &scion.Decoded{}, afterProcessing) }, - srcInterface: 1, - assertFunc: assert.Error, + srcInterface: 1, + egressInterface: 0, + assertFunc: assert.Error, }, "epic invalid timestamp": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -1146,8 +1475,9 @@ func TestProcessPkt(t *testing.T) { prepareEpicCrypto(t, spkt, epicpath, dpath, key) return toIP(t, spkt, epicpath, afterProcessing) }, - srcInterface: 1, - assertFunc: assert.Error, + srcInterface: 1, + egressInterface: 0, + assertFunc: assert.Error, }, "epic invalid LHVF": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { @@ -1164,8 +1494,9 @@ func TestProcessPkt(t *testing.T) { return toIP(t, spkt, epicpath, afterProcessing) }, - srcInterface: 1, - assertFunc: assert.Error, + srcInterface: 1, + egressInterface: 0, + assertFunc: assert.Error, }, } @@ -1188,6 +1519,7 @@ func TestProcessPkt(t *testing.T) { outPkt.Addr = nil } assert.Equal(t, want, outPkt) + assert.Equal(t, tc.egressInterface, result.EgressID) }) } } diff --git a/scion/traceroute/traceroute.go b/scion/traceroute/traceroute.go index d2805a30b..7ac6a6cb1 100644 --- a/scion/traceroute/traceroute.go +++ b/scion/traceroute/traceroute.go @@ -163,7 +163,10 @@ func (t *tracerouter) Traceroute(ctx context.Context) (Stats, error) { t.updateHandler(u) } } - xover := idxPath.IsXover() + // Peering links do not count as regular cross + // overs. For peering links we probe all interfaces on + // the path. + xover := idxPath.IsXover() && !info.Peer // The last hop of the path isn't probed, only the ingress interface is // relevant. // At a crossover (segment change) only the ingress interface is diff --git a/tools/braccept/cases/BUILD.bazel b/tools/braccept/cases/BUILD.bazel index c25dd33e9..30cb91f47 100644 --- a/tools/braccept/cases/BUILD.bazel +++ b/tools/braccept/cases/BUILD.bazel @@ -7,12 +7,14 @@ go_library( "child_to_child_xover.go", "child_to_internal.go", "child_to_parent.go", + "child_to_peer.go", "doc.go", "internal_to_child.go", "jumbo.go", "onehop.go", "parent_to_child.go", "parent_to_internal.go", + "peer_to_child.go", "scmp.go", "scmp_dest_unreachable.go", "scmp_expired_hop.go", @@ -33,6 +35,7 @@ go_library( "//pkg/drkey:go_default_library", "//pkg/private/util:go_default_library", "//pkg/private/xtest:go_default_library", + "//pkg/scrypto:go_default_library", "//pkg/slayers:go_default_library", "//pkg/slayers/path:go_default_library", "//pkg/slayers/path/empty:go_default_library", diff --git a/tools/braccept/cases/child_to_peer.go b/tools/braccept/cases/child_to_peer.go new file mode 100644 index 000000000..5d0d1081e --- /dev/null +++ b/tools/braccept/cases/child_to_peer.go @@ -0,0 +1,196 @@ +// Copyright 2023 SCION Association +// +// 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 cases + +import ( + "hash" + "net" + "path/filepath" + "time" + + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/private/util" + "github.com/scionproto/scion/pkg/private/xtest" + "github.com/scionproto/scion/pkg/scrypto" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/pkg/slayers/path/scion" + "github.com/scionproto/scion/tools/braccept/runner" +) + +// ChildToPeer tests transit traffic over one BR host and one peering hop. +// In this case, traffic enters via a regular link, and leaves via a peering link from +// the same router. To be valid, the path as to be constructed as one up segment over +// the normal link ending with a peering hop and one down segment starting at the +// peering link's destination. The peering hop is the second hop on the first segment +// as it crosses from a child interface to a peering interface. +// In this test case, the down segment is a one-hop segment. The peering link's destination +// is the only hop. +func ChildToPeer(artifactsDir string, mac hash.Hash) runner.Case { + options := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + + // We inject the packet into A (at IF 151) as if coming from 5 (at IF 511) + ethernet := &layers.Ethernet{ + SrcMAC: net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0xbe, 0xef}, // IF 511 + DstMAC: net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0x00, 0x15}, // IF 151 + EthernetType: layers.EthernetTypeIPv4, + } + + ip := &layers.IPv4{ // On the 5->A link + Version: 4, + IHL: 5, + TTL: 64, + SrcIP: net.IP{192, 168, 15, 3}, // from 5's 511 IP + DstIP: net.IP{192, 168, 15, 2}, // to A's 151 IP + Protocol: layers.IPProtocolUDP, + Flags: layers.IPv4DontFragment, + } + + udp := &layers.UDP{ + SrcPort: layers.UDPPort(40000), + DstPort: layers.UDPPort(50000), + } + _ = udp.SetNetworkLayerForChecksum(ip) + + sp := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 1, + CurrINF: 0, + SegLen: [3]uint8{2, 1, 0}, + }, + NumINF: 2, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + // up seg + { + SegID: 0x111, + ConsDir: false, + Timestamp: util.TimeToSecs(time.Now()), + Peer: true, + }, + // down seg + { + SegID: 0x222, + ConsDir: true, + Timestamp: util.TimeToSecs(time.Now()), + }, + }, + HopFields: []path.HopField{ + {ConsIngress: 511, ConsEgress: 0}, // at 5 leaving to A + {ConsIngress: 121, ConsEgress: 151}, // at A in from 5 out to 2 + {ConsIngress: 211, ConsEgress: 0}, // at 2 in coming from A + }, + } + + // Make the packet look the way it should... We have three hops of interrest. + + // Hops are all signed with different keys. Only HF[1] was signed by + // the AS that we hand the packet to. The others can be anything as they + // couldn't be check at that AS anyway. + macGenX, err := scrypto.InitMac([]byte("1234567812345678")) + if err != nil { + panic(err) + } + macGenY, err := scrypto.InitMac([]byte("abcdefghabcdefgh")) + if err != nil { + panic(err) + } + + // HF[1] is a peering hop, so it has the same SegID acc value as the next one + // in construction direction, HF[0]. That is, SEG[0]'s SegID. + sp.HopFields[1].Mac = path.MAC(mac, sp.InfoFields[0], sp.HopFields[1], nil) + sp.HopFields[0].Mac = path.MAC(macGenX, sp.InfoFields[0], sp.HopFields[0], nil) + + // The second segment has just one hop. + sp.HopFields[2].Mac = path.MAC(macGenY, sp.InfoFields[1], sp.HopFields[2], nil) + + // The message is ready for ingest at A, that is at HF[1]. Going against consruction + // direction, the SegID acc value must match that of HF[0], which is the same + // as that of HF[1], which is also SEG[0]'s SegID. So it's already correct. + + // The end-to-end trip is from 5,172.16.5.1 to 2,172.16.2.1 + // That won't change through forwarding. + scionL := &slayers.SCION{ + Version: 0, + TrafficClass: 0xb8, + FlowID: 0xdead, + NextHdr: slayers.L4UDP, + PathType: scion.PathType, + SrcIA: xtest.MustParseIA("1-ff00:0:5"), + DstIA: xtest.MustParseIA("1-ff00:0:2"), + Path: sp, + } + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.5.1")); err != nil { + panic(err) + } + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.2.1")); err != nil { + panic(err) + } + + scionudp := &slayers.UDP{} + scionudp.SrcPort = 40111 + scionudp.DstPort = 40222 + scionudp.SetNetworkLayerForChecksum(scionL) + + payload := []byte("actualpayloadbytes") + + // Prepare input packet + input := gopacket.NewSerializeBuffer() + if err := gopacket.SerializeLayers(input, options, + ethernet, ip, udp, scionL, scionudp, gopacket.Payload(payload), + ); err != nil { + panic(err) + } + + // Prepare want packet + // We expect it out of A's 121 IF on its way to 4's 211 IF. + + want := gopacket.NewSerializeBuffer() + ethernet.SrcMAC = net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0x00, 0x12} // IF 121 + ethernet.DstMAC = net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0xbe, 0xef} // IF 211 + ip.SrcIP = net.IP{192, 168, 12, 2} // from A's 121 IP + ip.DstIP = net.IP{192, 168, 12, 3} // to 2's 211 IP + udp.SrcPort, udp.DstPort = udp.DstPort, udp.SrcPort + if err := sp.IncPath(); err != nil { + panic(err) + } + + // Out of A, the current segment is seg 1. The Current acc + // value matches HF[2], which is SEG[1]'s SegID since HF[2] is the first hop in + // construction direction of the segment. + + if err := gopacket.SerializeLayers(want, options, + ethernet, ip, udp, scionL, scionudp, gopacket.Payload(payload), + ); err != nil { + panic(err) + } + + return runner.Case{ + Name: "ChildToChildPeeringOut", + WriteTo: "veth_151_host", // Where we inject the test packet + ReadFrom: "veth_121_host", // Where we capture the forwarded packet + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "ChildToChildXover"), + } +} diff --git a/tools/braccept/cases/doc.go b/tools/braccept/cases/doc.go index 9481e6215..843568dad 100644 --- a/tools/braccept/cases/doc.go +++ b/tools/braccept/cases/doc.go @@ -18,6 +18,13 @@ into the braccept binary. The process to add a new case is the following: +Step 0. Refer to the following for the test's setup: + - Overview: acceptance/router_multi/topology.drawio.png + - Topology Details: acceptance/router_multi/conf/topology.json + - MAC Addresses: acceptance/router_multi/test.py + Note that all MAC addresses of interfaces on the far side + of the A/B/C/D routers are identical: f00d:cafe:beef + Step 1. Add a new file with a representative name e.g. cases/child_to_child_xover.go @@ -45,7 +52,9 @@ Step 3. In the braccept/main.go, include the above function cases.ChildToChildXover(artifactsDir, mac), } -Step 4. Do a local run, which means set up a working router and execute the -braccept. +Step 4. Do a local run, which means set up a working router, execute the +braccept, shutdown the router. This is done in sequence by: + + bazel test acceptance/router_multi:all --config=integration --nocache_test_results */ package cases diff --git a/tools/braccept/cases/peer_to_child.go b/tools/braccept/cases/peer_to_child.go new file mode 100644 index 000000000..8c9d561fe --- /dev/null +++ b/tools/braccept/cases/peer_to_child.go @@ -0,0 +1,194 @@ +// Copyright 2023 SCION Association +// +// 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 cases + +import ( + "hash" + "net" + "path/filepath" + "time" + + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/private/util" + "github.com/scionproto/scion/pkg/private/xtest" + "github.com/scionproto/scion/pkg/scrypto" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/pkg/slayers/path/scion" + "github.com/scionproto/scion/tools/braccept/runner" +) + +// PeerToChild tests transit traffic over one BR host and one peering hop. +// In this case, traffic enters via a peering link, and leaves via a regular link from +// the same router. To be valid, the path as to be constructed as one up +// segment ending at the peering link's origin and one down segment over +// the regular link. The peering hop is the first hop on the second segment as +// it crosses from a peering interface to a child interface. +// In this test case, the up segment is a one-hop segment. The peering link's +// origin is the only hop. +func PeerToChild(artifactsDir string, mac hash.Hash) runner.Case { + options := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + + // We inject the packet into A (at IF 121) as if coming from 2 (at IF 211) + ethernet := &layers.Ethernet{ + SrcMAC: net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0xbe, 0xef}, // IF 211 + DstMAC: net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0x00, 0x12}, // IF 121 + EthernetType: layers.EthernetTypeIPv4, + } + + ip := &layers.IPv4{ // On the 2->A link + Version: 4, + IHL: 5, + TTL: 64, + SrcIP: net.IP{192, 168, 12, 3}, // from 2's 211 IP + DstIP: net.IP{192, 168, 12, 2}, // to A's 121 IP + Protocol: layers.IPProtocolUDP, + Flags: layers.IPv4DontFragment, + } + + udp := &layers.UDP{ + SrcPort: layers.UDPPort(40000), + DstPort: layers.UDPPort(50000), + } + _ = udp.SetNetworkLayerForChecksum(ip) + + sp := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 1, + CurrINF: 1, + SegLen: [3]uint8{1, 2, 0}, + }, + NumINF: 2, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + // up seg + { + SegID: 0x111, + ConsDir: false, + Timestamp: util.TimeToSecs(time.Now()), + }, + // down seg + { + SegID: 0x222, + ConsDir: true, + Timestamp: util.TimeToSecs(time.Now()), + Peer: true, + }, + }, + HopFields: []path.HopField{ + {ConsIngress: 211, ConsEgress: 0}, // at 2 out to A + {ConsIngress: 121, ConsEgress: 151}, // at A in from 2 out to 5 + {ConsIngress: 511, ConsEgress: 0}, // at 5 in from A + }, + } + + // Make the packet look the way it should... We have three hops of interrest. + + // Hops are all signed with different keys. Only HF[1] was signed by + // the AS that we hand the packet to. The others can be anything as they + // couldn't be check at that AS anyway. + macGenX, err := scrypto.InitMac([]byte("1234567812345678")) + if err != nil { + panic(err) + } + macGenY, err := scrypto.InitMac([]byte("abcdefghabcdefgh")) + if err != nil { + panic(err) + } + + // HF[0] is a regular hop. + sp.HopFields[0].Mac = path.MAC(macGenX, sp.InfoFields[0], sp.HopFields[0], nil) + + // HF[1] is a peering hop so it has the same SegID acc value as the next one + // in construction direction, HF[2]. That is, SEG[1]'s SegID. + sp.HopFields[1].Mac = path.MAC(mac, sp.InfoFields[1], sp.HopFields[1], nil) + sp.HopFields[2].Mac = path.MAC(macGenY, sp.InfoFields[1], sp.HopFields[2], nil) + + // The message if ready for ingest at A, that is at HF[1], the start of the + // second segment, in construction direction. So SegID is already correct. + + // The end-to-end trip is from 2,172.16.2.1 to 5,172.16.5.1 + // That won't change through forwarding. + scionL := &slayers.SCION{ + Version: 0, + TrafficClass: 0xb8, + FlowID: 0xdead, + NextHdr: slayers.L4UDP, + PathType: scion.PathType, + SrcIA: xtest.MustParseIA("1-ff00:0:2"), + DstIA: xtest.MustParseIA("1-ff00:0:5"), + Path: sp, + } + if err := scionL.SetSrcAddr(addr.MustParseHost("172.16.2.1")); err != nil { + panic(err) + } + if err := scionL.SetDstAddr(addr.MustParseHost("174.16.5.1")); err != nil { + panic(err) + } + + scionudp := &slayers.UDP{} + scionudp.SrcPort = 40111 + scionudp.DstPort = 40222 + scionudp.SetNetworkLayerForChecksum(scionL) + + payload := []byte("actualpayloadbytes") + + // Prepare input packet + input := gopacket.NewSerializeBuffer() + if err := gopacket.SerializeLayers(input, options, + ethernet, ip, udp, scionL, scionudp, gopacket.Payload(payload), + ); err != nil { + panic(err) + } + + // Prepare want packet + // We expect it out of A's 151 IF on its way to 5's 511 IF. + + want := gopacket.NewSerializeBuffer() + ethernet.SrcMAC = net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0x00, 0x15} // IF 151 + ethernet.DstMAC = net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0xbe, 0xef} // IF 511 + ip.SrcIP = net.IP{192, 168, 15, 2} // from A's 151 IP + ip.DstIP = net.IP{192, 168, 15, 3} // to 5's 511 IP + udp.SrcPort, udp.DstPort = udp.DstPort, udp.SrcPort + if err := sp.IncPath(); err != nil { + panic(err) + } + + // Out of A, the current segment is seg 1. The Current acc + // value is still the same since HF[1] is a peering hop. + + if err := gopacket.SerializeLayers(want, options, + ethernet, ip, udp, scionL, scionudp, gopacket.Payload(payload), + ); err != nil { + panic(err) + } + + return runner.Case{ + Name: "ChildToChildPeeringTransit", + WriteTo: "veth_121_host", // Where we inject the test packet + ReadFrom: "veth_151_host", // Where we capture the forwarded packet + Input: input.Bytes(), + Want: want.Bytes(), + StoreDir: filepath.Join(artifactsDir, "ChildToChildXover"), + } +} diff --git a/tools/braccept/main.go b/tools/braccept/main.go index 9a54104d5..fc27bf7af 100644 --- a/tools/braccept/main.go +++ b/tools/braccept/main.go @@ -128,6 +128,8 @@ func realMain() int { cases.OutgoingOneHop(artifactsDir, hfMAC), cases.SVC(artifactsDir, hfMAC), cases.JumboPacket(artifactsDir, hfMAC), + cases.ChildToPeer(artifactsDir, hfMAC), + cases.PeerToChild(artifactsDir, hfMAC), } if *bfd { diff --git a/tools/topology/topo.py b/tools/topology/topo.py index e92f8106c..298605bdc 100644 --- a/tools/topology/topo.py +++ b/tools/topology/topo.py @@ -298,6 +298,9 @@ def _gen_br_entry(self, local, l_ifid, remote, r_ifid, remote_type, attrs, r_ifid, link_addr_type) intl_addr = self._reg_addr(local, local_br + "_internal", addr_type) + + intf = self._gen_br_intf(remote, r_ifid, public_addr, remote_addr, attrs, remote_type) + if self.topo_dicts[local]["border_routers"].get(local_br) is None: intl_port = 30042 if not self.args.docker: @@ -306,24 +309,27 @@ def _gen_br_entry(self, local, l_ifid, remote, r_ifid, remote_type, attrs, self.topo_dicts[local]["border_routers"][local_br] = { 'internal_addr': join_host_port(intl_addr.ip, intl_port), 'interfaces': { - l_ifid: self._gen_br_intf(remote, public_addr, remote_addr, attrs, remote_type) + l_ifid: intf } } else: # There is already a BR entry, add interface - intf = self._gen_br_intf(remote, public_addr, remote_addr, attrs, remote_type) self.topo_dicts[local]["border_routers"][local_br]['interfaces'][l_ifid] = intf - def _gen_br_intf(self, remote, public_addr, remote_addr, attrs, remote_type): - return { + def _gen_br_intf(self, remote, r_ifid, public_addr, remote_addr, attrs, remote_type): + link_to = remote_type.name.lower() + intf = { 'underlay': { 'public': join_host_port(public_addr.ip, SCION_ROUTER_PORT), 'remote': join_host_port(remote_addr.ip, SCION_ROUTER_PORT), }, 'isd_as': str(remote), - 'link_to': remote_type.name.lower(), - 'mtu': attrs.get('mtu', self.args.default_mtu) + 'link_to': link_to, + 'mtu': attrs.get('mtu', self.args.default_mtu), } + if link_to == 'peer': + intf['remote_interface_id'] = r_ifid + return intf def _gen_sig_entries(self, topo_id, as_conf): addr_type = addr_type_from_underlay(as_conf.get('underlay', DEFAULT_UNDERLAY)) diff --git a/topology/peering-test-multi.topo b/topology/peering-test-multi.topo new file mode 100644 index 000000000..b32873948 --- /dev/null +++ b/topology/peering-test-multi.topo @@ -0,0 +1,41 @@ +--- # Topology demonstrating peering, IPv4 Only +ASes: + "1-ff00:0:110": + core: true + voting: true + authoritative: true + issuing: true + mtu: 1400 + "1-ff00:0:111": + cert_issuer: 1-ff00:0:110 + "1-ff00:0:112": + cert_issuer: 1-ff00:0:110 + "1-ff00:0:113": + cert_issuer: 1-ff00:0:110 + "1-ff00:0:114": + cert_issuer: 1-ff00:0:110 + "2-ff00:0:210": + core: true + voting: true + authoritative: true + issuing: true + mtu: 1400 + "2-ff00:0:211": + cert_issuer: 2-ff00:0:210 + "2-ff00:0:212": + cert_issuer: 2-ff00:0:210 + "2-ff00:0:213": + cert_issuer: 2-ff00:0:210 + + +links: + - {a: "1-ff00:0:110#1", b: "1-ff00:0:111#41", linkAtoB: CHILD, mtu: 1280} + - {a: "1-ff00:0:110#2", b: "1-ff00:0:112#1", linkAtoB: CHILD, bw: 500} + - {a: "1-ff00:0:112#3", b: "1-ff00:0:113#3", linkAtoB: CHILD, bw: 500} + - {a: "1-ff00:0:113#4", b: "1-ff00:0:114#4", linkAtoB: CHILD, bw: 500} + - {a: "1-ff00:0:112#47", b: "1-ff00:0:114#11", linkAtoB: PEER} + - {a: "1-ff00:0:110#3", b: "2-ff00:0:210#3", linkAtoB: CORE} + - {a: "2-ff00:0:210#1", b: "2-ff00:0:211#3", linkAtoB: CHILD, mtu: 1280} + - {a: "2-ff00:0:210#2", b: "2-ff00:0:212#7", linkAtoB: CHILD, bw: 500} + - {a: "2-ff00:0:212#3", b: "2-ff00:0:213#3", linkAtoB: CHILD, bw: 500} + - {a: "1-ff00:0:112#42", b: "2-ff00:0:212#23", linkAtoB: PEER} diff --git a/topology/peering-test.topo b/topology/peering-test.topo new file mode 100644 index 000000000..3f52f7cfe --- /dev/null +++ b/topology/peering-test.topo @@ -0,0 +1,40 @@ +--- # Topology demonstrating peering, IPv4 Only +ASes: + "1-ff00:0:110": + core: true + voting: true + authoritative: true + issuing: true + mtu: 1400 + "1-ff00:0:111": + cert_issuer: 1-ff00:0:110 + "1-ff00:0:112": + cert_issuer: 1-ff00:0:110 + "1-ff00:0:113": + cert_issuer: 1-ff00:0:110 + "1-ff00:0:114": + cert_issuer: 1-ff00:0:110 + "2-ff00:0:210": + core: true + voting: true + authoritative: true + issuing: true + mtu: 1400 + "2-ff00:0:211": + cert_issuer: 2-ff00:0:210 + "2-ff00:0:212": + cert_issuer: 2-ff00:0:210 + "2-ff00:0:213": + cert_issuer: 2-ff00:0:210 + + +links: + - {a: "1-ff00:0:110#1", b: "1-ff00:0:111#41", linkAtoB: CHILD, mtu: 1280} + - {a: "1-ff00:0:110#2", b: "1-ff00:0:112#1", linkAtoB: CHILD, bw: 500} + - {a: "1-ff00:0:112#3", b: "1-ff00:0:113#3", linkAtoB: CHILD, bw: 500} + - {a: "1-ff00:0:113#4", b: "1-ff00:0:114#4", linkAtoB: CHILD, bw: 500} + - {a: "1-ff00:0:110#3", b: "2-ff00:0:210#3", linkAtoB: CORE} + - {a: "2-ff00:0:210#1", b: "2-ff00:0:211#3", linkAtoB: CHILD, mtu: 1280} + - {a: "2-ff00:0:210#2", b: "2-ff00:0:212#7", linkAtoB: CHILD, bw: 500} + - {a: "2-ff00:0:212#3", b: "2-ff00:0:213#3", linkAtoB: CHILD, bw: 500} + - {a: "1-ff00:0:112#42", b: "2-ff00:0:212#23", linkAtoB: PEER} From ae14b74ec94fbc83588ba4258ee4493d1d09e898 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Mon, 25 Sep 2023 18:24:08 +0200 Subject: [PATCH 056/255] build: prevent go from linking libresolv dynamically. (#4394) This is default (https://pkg.go.dev/net@go1.21.1#hdr-Name_Resolution). It creates an indirect dependency on a fresh version of glibc. As a result, it prevents our binaries from running on not-so-fesh docker images. --- .bazelrc | 5 +++-- BUILD.bazel | 46 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/.bazelrc b/.bazelrc index 0b4fa25f9..3dbfc2dbc 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,5 +1,5 @@ ### common options for all subcommands (help, query, build, ...) -common --show_timestamps +common --show_timestamps --enable_platform_specific_config # connect to buchgr/bazel-remote cache # These flags can unfortunately not be specified for `common`, as they are not accepted by all subcommands (help, version, dump) @@ -17,7 +17,8 @@ build --incompatible_default_to_explicit_init_py # include one of "--define gotags=sqlite_mattn" or "--define gotags=sqlite_modernc" # cannot be in common, because query chokes on it. -build --define gotags=sqlite_modernc +build --define gotags=sqlite_modernc,netgo +build:osx --define gotags=sqlite_modernc ### options for test test --build_tests_only --print_relative_test_log_paths --test_output=errors diff --git a/BUILD.bazel b/BUILD.bazel index e70dded2a..be76b0e6c 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -34,6 +34,20 @@ load("@cgrindel_bazel_starlib//updatesrc:defs.bzl", "updatesrc_update_all") # # This is simplistic but the complete, by-the-everchanging-bazel-book, solution # is ludicrously complicated. Go there if and when needed. +config_setting( + name = "sqlite_mattn_netgo", + define_values = { + "gotags": "sqlite_mattn,netgo", + }, +) + +config_setting( + name = "sqlite_modernc_netgo", + define_values = { + "gotags": "sqlite_modernc,netgo", + }, +) + config_setting( name = "sqlite_mattn", define_values = { @@ -61,8 +75,20 @@ config_setting( gazelle( name = "gazelle", build_tags = select({ - ":sqlite_modernc": ["sqlite_modernc"], - ":sqlite_mattn": ["sqlite_mattn"], + ":sqlite_modernc_netgo": [ + "sqlite_modernc", + "sqlite_modernc_netgo", + ], + ":sqlite_modernc": [ + "sqlite_modernc", + ], + ":sqlite_mattn_netgo": [ + "sqlite_mattn", + "netgo", + ], + ":sqlite_mattn": [ + "sqlite_mattn", + ], }), command = "update", extra_args = [ @@ -76,8 +102,20 @@ gazelle( gazelle( name = "gazelle_diff", build_tags = select({ - ":sqlite_modernc": ["sqlite_modernc"], - ":sqlite_mattn": ["sqlite_mattn"], + ":sqlite_modernc_netgo": [ + "sqlite_modernc", + "netgo", + ], + ":sqlite_modernc": [ + "sqlite_modernc", + ], + ":sqlite_mattn_netgo": [ + "sqlite_mattn", + "netgo", + ], + ":sqlite_mattn": [ + "sqlite_mattn", + ], }), command = "update", extra_args = [ From c7b2c09050efe4566478994abebd08254631387c Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Mon, 25 Sep 2023 21:32:36 +0200 Subject: [PATCH 057/255] ci: fixes for updated buildkite elastic stack version (#4397) Fixes for update of buildkite elastic stack to v6.7.1. Update package "rhel" dependency list for Amazon Linux 2023: - `bridge-utils`: no longer available. Replace deprecated `brctl` with iproute2's `bridge` - `moreutils`: no longer available, not used - `sqlite3`: no longer available, not used - `ethtool`: required for router_multi test, seems to have previously been installed by default. For the router_multi test, set the default TTL to 64, so that the packets sent back by the router match the expected value. This is the default value on many other systems, so we did not previously need to worry about this. The value is only set in a net-namespace, so we don't need to worry about resetting it. --- acceptance/router_multi/test.py | 4 ++++ demo/file_transfer/tc_setup.sh | 2 +- doc/dev/testing/buildkite.rst | 11 ++++++----- tools/env/rhel/pkgs.txt | 4 +--- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/acceptance/router_multi/test.py b/acceptance/router_multi/test.py index fe18bbdc7..449738449 100644 --- a/acceptance/router_multi/test.py +++ b/acceptance/router_multi/test.py @@ -118,6 +118,10 @@ def teardown(self): sudo("chown -R %s %s" % (cmd.whoami(), self.artifacts)) def create_veths(self, ns: str): + # Set default TTL for outgoing packets to the common value 64, so that packets sent + # from router will match the expected value. + sudo("ip netns exec %s sysctl -w net.ipv4.ip_default_ttl=64" % ns) + create_veth("veth_int_host", "veth_int", "192.168.0.11/24", "f0:0d:ca:fe:00:01", ns, ["192.168.0.12", "192.168.0.13", "192.168.0.14", "192.168.0.51", "192.168.0.61", "192.168.0.71"]) diff --git a/demo/file_transfer/tc_setup.sh b/demo/file_transfer/tc_setup.sh index 9785adecf..730ee9c86 100755 --- a/demo/file_transfer/tc_setup.sh +++ b/demo/file_transfer/tc_setup.sh @@ -4,7 +4,7 @@ set -ex NETWORK=$1 RATE=$2 -veths=$(brctl show $NETWORK | awk 'NR>1''{print $NF}') +veths=$(bridge link show | awk "/$NETWORK/{print \$2}") for veth in $veths do echo $veth diff --git a/doc/dev/testing/buildkite.rst b/doc/dev/testing/buildkite.rst index a83f19462..c7cd1f1bd 100644 --- a/doc/dev/testing/buildkite.rst +++ b/doc/dev/testing/buildkite.rst @@ -44,12 +44,13 @@ Agents Machine Image ------------- -We use the default machine image of the *Elastic CI Stack for AWS*. `What's on each machine `_: +We use the default machine image of the *Elastic CI Stack for AWS* release `v6.7.1 `. +`What's on each machine `_: -- Amazon Linux 2 -- Buildkite Agent v3.39.1 -- Docker v20.10.7 -- Docker Compose v1.29.2 +- Amazon Linux 2023 +- Buildkite Agent v3.50.2 +- Docker v20.10.25 +- Docker Compose v2.20.3 - AWS CLI - jq diff --git a/tools/env/rhel/pkgs.txt b/tools/env/rhel/pkgs.txt index 737fe222c..406131757 100644 --- a/tools/env/rhel/pkgs.txt +++ b/tools/env/rhel/pkgs.txt @@ -1,10 +1,8 @@ -bridge-utils -moreutils +ethtool gcc g++ python3-pip python3-setuptools python3-wheel jq -sqlite3 openssl From ba355f1bbebba054d36b0d883ce6b675d8ed3fc3 Mon Sep 17 00:00:00 2001 From: JordiSubira Date: Tue, 26 Sep 2023 18:21:53 +0200 Subject: [PATCH 058/255] spao: Update timestamp / Sequence Number field (#4366) This PR introduces modification on the SPAO header. More concretely, the changes concerning the Timestamp / Sequence Number field specified in #4300. --- control/cmd/control/BUILD.bazel | 2 +- control/cmd/control/main.go | 20 +--- control/config/drkey.go | 8 +- pkg/drkey/drkey.go | 4 +- pkg/slayers/pkt_auth.go | 80 +++++-------- pkg/slayers/pkt_auth_test.go | 43 ++----- pkg/spao/BUILD.bazel | 4 +- pkg/spao/mac.go | 15 +-- pkg/spao/mac_test.go | 57 +++++---- pkg/spao/timestamp.go | 27 ++--- pkg/spao/timestamp_test.go | 72 +++++++++++ private/drkey/drkeyutil/BUILD.bazel | 19 +++ private/drkey/drkeyutil/drkey.go | 58 +++++++++ private/drkey/drkeyutil/provider.go | 115 ++++++++++++++++++ router/BUILD.bazel | 1 + router/dataplane.go | 88 ++++++-------- tools/braccept/cases/BUILD.bazel | 1 + tools/braccept/cases/scmp.go | 19 ++- tools/braccept/cases/scmp_expired_hop.go | 145 +++-------------------- tools/braccept/cases/scmp_invalid_mac.go | 3 +- tools/braccept/cases/scmp_traceroute.go | 32 +++-- tools/braccept/main.go | 9 +- 22 files changed, 459 insertions(+), 363 deletions(-) create mode 100644 pkg/spao/timestamp_test.go create mode 100644 private/drkey/drkeyutil/BUILD.bazel create mode 100644 private/drkey/drkeyutil/drkey.go create mode 100644 private/drkey/drkeyutil/provider.go diff --git a/control/cmd/control/BUILD.bazel b/control/cmd/control/BUILD.bazel index ad9a6938a..5d2dfa81e 100644 --- a/control/cmd/control/BUILD.bazel +++ b/control/cmd/control/BUILD.bazel @@ -33,7 +33,6 @@ go_library( "//pkg/private/common:go_default_library", "//pkg/private/prom:go_default_library", "//pkg/private/serrors:go_default_library", - "//pkg/private/util:go_default_library", "//pkg/proto/control_plane:go_default_library", "//pkg/proto/discovery:go_default_library", "//pkg/scrypto:go_default_library", @@ -48,6 +47,7 @@ go_library( "//private/ca/renewal:go_default_library", "//private/ca/renewal/grpc:go_default_library", "//private/discovery:go_default_library", + "//private/drkey/drkeyutil:go_default_library", "//private/keyconf:go_default_library", "//private/mgmtapi/cppki/api:go_default_library", "//private/mgmtapi/jwtauth:go_default_library", diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index d5de9e08f..1b192cf13 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -22,7 +22,6 @@ import ( "fmt" "net/http" _ "net/http/pprof" - "os" "path/filepath" "strings" "sync" @@ -61,7 +60,6 @@ import ( "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/prom" "github.com/scionproto/scion/pkg/private/serrors" - "github.com/scionproto/scion/pkg/private/util" cppb "github.com/scionproto/scion/pkg/proto/control_plane" dpb "github.com/scionproto/scion/pkg/proto/discovery" "github.com/scionproto/scion/pkg/scrypto" @@ -76,6 +74,7 @@ import ( "github.com/scionproto/scion/private/ca/renewal" renewalgrpc "github.com/scionproto/scion/private/ca/renewal/grpc" "github.com/scionproto/scion/private/discovery" + "github.com/scionproto/scion/private/drkey/drkeyutil" "github.com/scionproto/scion/private/keyconf" cppkiapi "github.com/scionproto/scion/private/mgmtapi/cppki/api" "github.com/scionproto/scion/private/mgmtapi/jwtauth" @@ -587,10 +586,7 @@ func realMain(ctx context.Context) error { var drkeyEngine *drkey.ServiceEngine var epochDuration time.Duration if globalCfg.DRKey.Enabled() { - epochDuration, err = loadEpochDuration() - if err != nil { - return err - } + epochDuration = drkeyutil.LoadEpochDuration() log.Debug("DRKey debug info", "epoch duration", epochDuration.String()) masterKey, err := loadMasterSecret(globalCfg.General.ConfigDir) if err != nil { @@ -980,15 +976,3 @@ func loadMasterSecret(dir string) (keyconf.Master, error) { } return masterKey, nil } - -func loadEpochDuration() (time.Duration, error) { - s := os.Getenv(config.EnvVarEpochDuration) - if s == "" { - return config.DefaultEpochDuration, nil - } - duration, err := util.ParseDuration(s) - if err != nil { - return 0, serrors.WrapStr("parsing SCION_TESTING_DRKEY_EPOCH_DURATION", err) - } - return duration, nil -} diff --git a/control/config/drkey.go b/control/config/drkey.go index 27df174c2..9a4478677 100644 --- a/control/config/drkey.go +++ b/control/config/drkey.go @@ -18,7 +18,6 @@ import ( "io" "net/netip" "strings" - "time" "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/serrors" @@ -26,12 +25,7 @@ import ( "github.com/scionproto/scion/private/storage" ) -const ( - // DefaultEpochDuration is the default duration for the drkey SecretValue and derived keys - DefaultEpochDuration = 24 * time.Hour - DefaultPrefetchEntries = 10000 - EnvVarEpochDuration = "SCION_TESTING_DRKEY_EPOCH_DURATION" -) +const DefaultPrefetchEntries = 10000 var _ (config.Config) = (*DRKeyConfig)(nil) diff --git a/pkg/drkey/drkey.go b/pkg/drkey/drkey.go index a54b4a708..23811a88f 100644 --- a/pkg/drkey/drkey.go +++ b/pkg/drkey/drkey.go @@ -44,8 +44,8 @@ type Epoch struct { func NewEpoch(begin, end uint32) Epoch { return Epoch{ cppki.Validity{ - NotBefore: util.SecsToTime(begin).UTC(), - NotAfter: util.SecsToTime(end).UTC(), + NotBefore: util.SecsToTime(begin), + NotAfter: util.SecsToTime(end), }, } } diff --git a/pkg/slayers/pkt_auth.go b/pkg/slayers/pkt_auth.go index eb3db8115..b9da278d0 100644 --- a/pkg/slayers/pkt_auth.go +++ b/pkg/slayers/pkt_auth.go @@ -21,9 +21,9 @@ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | Security Parameter Index | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Algorithm | Timestamp | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | RSV | Sequence Number | +// | Algorithm | RSV | | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +// | Timestamp / Sequence Number | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | | // + + @@ -52,17 +52,12 @@ const ( PacketAuthReceiverSide ) -const ( - PacketAuthLater uint8 = iota - PacketAuthEarlier -) - const ( // PacketAuthOptionMetadataLen is the size of the SPAO Metadata and // corresponds the minimum size of the SPAO OptData. // The SPAO header contains the following fixed-length fields: - // SPI (4 Bytes), Algorithm (1 Byte), Timestamp (3 Bytes), - // RSV (1 Byte) and Sequence Number (3 Bytes). + // SPI (4 Bytes), Algorithm (1 Byte), RSV (1 Byte) and + // Timestamp / Sequence Number (6 Bytes). PacketAuthOptionMetadataLen = 12 ) @@ -72,26 +67,19 @@ const ( type PacketAuthSPI uint32 func (p PacketAuthSPI) Type() uint8 { - if p&(1<<18) == 0 { + if p&(1<<17) == 0 { return PacketAuthASHost } return PacketAuthHostHost } func (p PacketAuthSPI) Direction() uint8 { - if p&(1<<17) == 0 { + if p&(1<<16) == 0 { return PacketAuthSenderSide } return PacketAuthReceiverSide } -func (p PacketAuthSPI) Epoch() uint8 { - if p&(1<<16) == 0 { - return PacketAuthLater - } - return PacketAuthEarlier -} - func (p PacketAuthSPI) DRKeyProto() uint16 { return uint16(p) } @@ -104,7 +92,6 @@ func MakePacketAuthSPIDRKey( proto uint16, drkeyType uint8, dir uint8, - epoch uint8, ) (PacketAuthSPI, error) { if proto < 1 { @@ -116,12 +103,8 @@ func MakePacketAuthSPIDRKey( if dir > 1 { return 0, serrors.New("Invalid DRKeyDirection value") } - if epoch > 1 { - return 0, serrors.New("Invalid DRKeyEpochType value") - } - spi := uint32((drkeyType & 0x1)) << 18 - spi |= uint32((dir & 0x1)) << 17 - spi |= uint32((epoch & 0x1)) << 16 + spi := uint32((drkeyType & 0x1)) << 17 + spi |= uint32((dir & 0x1)) << 16 spi |= uint32(proto) return PacketAuthSPI(spi), nil @@ -137,11 +120,10 @@ const ( ) type PacketAuthOptionParams struct { - SPI PacketAuthSPI - Algorithm PacketAuthAlg - Timestamp uint32 - SequenceNumber uint32 - Auth []byte + SPI PacketAuthSPI + Algorithm PacketAuthAlg + TimestampSN uint64 + Auth []byte } // PacketAuthOption wraps an EndToEndOption of OptTypeAuthenticator. @@ -185,11 +167,8 @@ func (o PacketAuthOption) Reset( p PacketAuthOptionParams, ) error { - if p.Timestamp >= (1 << 24) { - return serrors.New("Timestamp value should be smaller than 2^24") - } - if p.SequenceNumber >= (1 << 24) { - return serrors.New("Sequence number should be smaller than 2^24") + if p.TimestampSN >= (1 << 48) { + return serrors.New("Timestamp value should be smaller than 2^48") } o.OptType = OptTypeAuthenticator @@ -202,13 +181,8 @@ func (o PacketAuthOption) Reset( } binary.BigEndian.PutUint32(o.OptData[:4], uint32(p.SPI)) o.OptData[4] = byte(p.Algorithm) - o.OptData[5] = byte(p.Timestamp >> 16) - o.OptData[6] = byte(p.Timestamp >> 8) - o.OptData[7] = byte(p.Timestamp) - o.OptData[8] = byte(0) - o.OptData[9] = byte(p.SequenceNumber >> 16) - o.OptData[10] = byte(p.SequenceNumber >> 8) - o.OptData[11] = byte(p.SequenceNumber) + o.OptData[5] = byte(0) + bigEndianPutUint48(o.OptData[6:12], p.TimestampSN) copy(o.OptData[12:], p.Auth) o.OptAlign = [2]uint8{4, 2} @@ -229,13 +203,8 @@ func (o PacketAuthOption) Algorithm() PacketAuthAlg { } // Timestamp returns the value set in the homonym field in the extension. -func (o PacketAuthOption) Timestamp() uint32 { - return uint32(o.OptData[5])<<16 + uint32(o.OptData[6])<<8 + uint32(o.OptData[7]) -} - -// SequenceNumber returns the value set in the homonym field in the extension. -func (o PacketAuthOption) SequenceNumber() uint32 { - return uint32(o.OptData[9])<<16 + uint32(o.OptData[10])<<8 + uint32(o.OptData[11]) +func (o PacketAuthOption) TimestampSN() uint64 { + return bigEndianUint48(o.OptData[6:12]) } // Authenticator returns slice of the underlying auth buffer. @@ -244,3 +213,14 @@ func (o PacketAuthOption) SequenceNumber() uint32 { func (o PacketAuthOption) Authenticator() []byte { return o.OptData[12:] } + +func bigEndianUint48(b []byte) uint64 { + return uint64(b[0])<<40 + uint64(b[1])<<32 + + uint64(binary.BigEndian.Uint32(b[2:6])) +} + +func bigEndianPutUint48(b []byte, v uint64) { + b[0] = byte(v >> 40) + b[1] = byte(v >> 32) + binary.BigEndian.PutUint32(b[2:6], uint32(v)) +} diff --git a/pkg/slayers/pkt_auth_test.go b/pkg/slayers/pkt_auth_test.go index 1b102192e..5cb5a9fa7 100644 --- a/pkg/slayers/pkt_auth_test.go +++ b/pkg/slayers/pkt_auth_test.go @@ -27,17 +27,16 @@ import ( var ( algo = slayers.PacketAuthSHA1_AES_CBC - ts = uint32(0x030201) - sn = uint32(0x060504) + ts = uint64(0x060504030201) optAuthMAC = []byte("16byte_mac_foooo") ) var rawE2EOptAuth = append( []byte{ 0x11, 0x7, 0x2, 0x1c, - 0x0, 0x2, 0x0, 0x1, - 0x1, 0x3, 0x2, 0x1, - 0x0, 0x6, 0x5, 0x4, + 0x0, 0x1, 0x0, 0x1, + 0x1, 0x0, 0x6, 0x5, + 0x4, 0x3, 0x2, 0x1, }, optAuthMAC..., ) @@ -47,8 +46,7 @@ func TestOptAuthenticatorSerialize(t *testing.T) { name string spiFunc func(t *testing.T) slayers.PacketAuthSPI algo slayers.PacketAuthAlg - ts uint32 - sn uint32 + ts uint64 optAuth []byte errorFunc assert.ErrorAssertionFunc }{ @@ -57,7 +55,6 @@ func TestOptAuthenticatorSerialize(t *testing.T) { spiFunc: initSPI, algo: algo, ts: ts, - sn: sn, optAuth: optAuthMAC, errorFunc: assert.NoError, }, @@ -65,17 +62,7 @@ func TestOptAuthenticatorSerialize(t *testing.T) { name: "bad_ts", spiFunc: initSPI, algo: algo, - ts: binary.LittleEndian.Uint32([]byte{0, 0, 0, 1}), - sn: sn, - optAuth: optAuthMAC, - errorFunc: assert.Error, - }, - { - name: "bad_sn", - spiFunc: initSPI, - algo: algo, - ts: ts, - sn: binary.LittleEndian.Uint32([]byte{0, 0, 0, 1}), + ts: uint64(1 << 48), optAuth: optAuthMAC, errorFunc: assert.Error, }, @@ -84,11 +71,10 @@ func TestOptAuthenticatorSerialize(t *testing.T) { t.Run(c.name, func(t *testing.T) { spao, err := slayers.NewPacketAuthOption(slayers.PacketAuthOptionParams{ - SPI: c.spiFunc(t), - Algorithm: c.algo, - Timestamp: c.ts, - SequenceNumber: c.sn, - Auth: c.optAuth, + SPI: c.spiFunc(t), + Algorithm: c.algo, + TimestampSN: c.ts, + Auth: c.optAuth, }) c.errorFunc(t, err) if err != nil { @@ -122,17 +108,15 @@ func TestOptAuthenticatorDeserialize(t *testing.T) { assert.Equal(t, initSPI(t), auth.SPI(), "SPI") assert.Equal(t, slayers.PacketAuthASHost, auth.SPI().Type()) assert.Equal(t, slayers.PacketAuthReceiverSide, auth.SPI().Direction()) - assert.Equal(t, slayers.PacketAuthLater, auth.SPI().Epoch()) assert.Equal(t, true, auth.SPI().IsDRKey()) assert.Equal(t, algo, auth.Algorithm(), "Algorithm Type") - assert.Equal(t, ts, auth.Timestamp(), "Timestamp") - assert.Equal(t, sn, auth.SequenceNumber(), "Sequence Number") + assert.Equal(t, ts, auth.TimestampSN(), "TimestampSN") assert.Equal(t, optAuthMAC, auth.Authenticator(), "Authenticator data (MAC)") } func TestMakePacketAuthSPIDrkey(t *testing.T) { spi := initSPI(t) - assert.EqualValues(t, binary.BigEndian.Uint32([]byte{0, 2, 0, 1}), spi) + assert.EqualValues(t, binary.BigEndian.Uint32([]byte{0, 1, 0, 1}), spi) } func TestOptAuthenticatorDeserializeCorrupt(t *testing.T) { @@ -159,8 +143,7 @@ func initSPI(t *testing.T) slayers.PacketAuthSPI { spi, err := slayers.MakePacketAuthSPIDRKey( 1, slayers.PacketAuthASHost, - slayers.PacketAuthReceiverSide, - slayers.PacketAuthLater) + slayers.PacketAuthReceiverSide) require.NoError(t, err) return spi } diff --git a/pkg/spao/BUILD.bazel b/pkg/spao/BUILD.bazel index 390c3f26c..69eda0ed2 100644 --- a/pkg/spao/BUILD.bazel +++ b/pkg/spao/BUILD.bazel @@ -10,8 +10,8 @@ go_library( importpath = "github.com/scionproto/scion/pkg/spao", visibility = ["//visibility:public"], deps = [ + "//pkg/drkey:go_default_library", "//pkg/private/serrors:go_default_library", - "//pkg/private/util:go_default_library", "//pkg/slayers:go_default_library", "//pkg/slayers/path:go_default_library", "//pkg/slayers/path/empty:go_default_library", @@ -27,6 +27,7 @@ go_test( srcs = [ "export_test.go", "mac_test.go", + "timestamp_test.go", ], embed = [":go_default_library"], deps = [ @@ -38,6 +39,7 @@ go_test( "//pkg/slayers/path/epic:go_default_library", "//pkg/slayers/path/onehop:go_default_library", "//pkg/slayers/path/scion:go_default_library", + "//private/drkey/drkeyutil:go_default_library", "@com_github_dchest_cmac//:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/pkg/spao/mac.go b/pkg/spao/mac.go index d594ef88d..6ef8687f9 100644 --- a/pkg/spao/mac.go +++ b/pkg/spao/mac.go @@ -127,13 +127,8 @@ func serializeAuthenticatedData( buf[1] = byte(pldType) binary.BigEndian.PutUint16(buf[2:], uint16(len(pld))) buf[4] = byte(opt.Algorithm()) - buf[5] = byte(opt.Timestamp() >> 16) - buf[6] = byte(opt.Timestamp() >> 8) - buf[7] = byte(opt.Timestamp()) - buf[8] = byte(0) - buf[9] = byte(opt.SequenceNumber() >> 16) - buf[10] = byte(opt.SequenceNumber() >> 8) - buf[11] = byte(opt.SequenceNumber()) + buf[5] = byte(0) + bigEndianPutUint48(buf[6:12], opt.TimestampSN()) firstHdrLine := uint32(s.Version&0xF)<<28 | uint32(s.TrafficClass&0x3f)<<20 | s.FlowID&0xFFFFF binary.BigEndian.PutUint32(buf[12:], firstHdrLine) buf[16] = byte(s.PathType) @@ -212,3 +207,9 @@ func zeroOutWithBase(base scion.Base, buf []byte) { } } } + +func bigEndianPutUint48(b []byte, v uint64) { + b[0] = byte(v >> 40) + b[1] = byte(v >> 32) + binary.BigEndian.PutUint32(b[2:6], uint32(v)) +} diff --git a/pkg/spao/mac_test.go b/pkg/spao/mac_test.go index 08e6e8c16..3b74398ab 100644 --- a/pkg/spao/mac_test.go +++ b/pkg/spao/mac_test.go @@ -39,7 +39,6 @@ func TestComputeAuthMac(t *testing.T) { srcIA := xtest.MustParseIA("1-ff00:0:111") dstIA := xtest.MustParseIA("1-ff00:0:112") authKey := drkey.Key{0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7} - sn := uint32(0x060504) ts := uint32(0x030201) fooPayload := []byte("some payload") decodedPath := &scion.Decoded{ @@ -108,11 +107,10 @@ func TestComputeAuthMac(t *testing.T) { }{ "empty": { optionParameter: slayers.PacketAuthOptionParams{ - SPI: slayers.PacketAuthSPI(0x1), - Algorithm: slayers.PacketAuthCMAC, - Timestamp: 0x3e8, - SequenceNumber: sn, - Auth: make([]byte, 16), + SPI: slayers.PacketAuthSPI(0x1), + Algorithm: slayers.PacketAuthCMAC, + TimestampSN: 0x060504030201, + Auth: make([]byte, 16), }, scionL: slayers.SCION{ FlowID: binary.BigEndian.Uint32([]byte{0x00, 0x00, 0x12, 0x34}), @@ -131,8 +129,9 @@ func TestComputeAuthMac(t *testing.T) { rawMACInput: append([]byte{ // 1. Authenticator Option Metadata 0x9, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length - 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp - 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number + 0x0, 0x0, // Algorithm | RSV + 0x6, 0x5, 0x4, 0x3, // Timestamp / Sequence Number + 0x2, 0x1, // 2. SCION Common Header 0x3, 0xf0, 0x12, 0x34, // Version | TrafficClass | FlowID 0x0, 0x0, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV @@ -143,11 +142,10 @@ func TestComputeAuthMac(t *testing.T) { }, "decoded": { optionParameter: slayers.PacketAuthOptionParams{ - SPI: slayers.PacketAuthSPI(0x1), - Algorithm: slayers.PacketAuthCMAC, - Timestamp: 0x3e8, - SequenceNumber: sn, - Auth: make([]byte, 16), + SPI: slayers.PacketAuthSPI(0x1), + Algorithm: slayers.PacketAuthCMAC, + TimestampSN: 0x060504030201, + Auth: make([]byte, 16), }, scionL: slayers.SCION{ FlowID: binary.BigEndian.Uint32([]byte{0x00, 0x00, 0x12, 0x34}), @@ -166,8 +164,9 @@ func TestComputeAuthMac(t *testing.T) { rawMACInput: append([]byte{ // 1. Authenticator Option Metadata 0x1c, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length - 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp - 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number + 0x0, 0x0, // Algorithm | RSV + 0x6, 0x5, 0x4, 0x3, // Timestamp / Sequence Number + 0x2, 0x1, // 2. SCION Common Header 0x3, 0xf0, 0x12, 0x34, // Version | TrafficClass | FlowID 0x1, 0x43, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV @@ -198,11 +197,10 @@ func TestComputeAuthMac(t *testing.T) { }, "one hop": { optionParameter: slayers.PacketAuthOptionParams{ - SPI: slayers.PacketAuthSPI(0x1), - Algorithm: slayers.PacketAuthCMAC, - Timestamp: 0x3e8, - SequenceNumber: sn, - Auth: make([]byte, 16), + SPI: slayers.PacketAuthSPI(0x1), + Algorithm: slayers.PacketAuthCMAC, + TimestampSN: 0x060504030201, + Auth: make([]byte, 16), }, scionL: slayers.SCION{ FlowID: binary.BigEndian.Uint32([]byte{0x00, 0x00, 0x12, 0x34}), @@ -242,8 +240,9 @@ func TestComputeAuthMac(t *testing.T) { rawMACInput: append([]byte{ // 1. Authenticator Option Metadata 0x11, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length - 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp - 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number + 0x0, 0x0, // Algorithm | RSV + 0x6, 0x5, 0x4, 0x3, // Timestamp / Sequence Number + 0x2, 0x1, // 2. SCION Common Header 0x3, 0xf0, 0x12, 0x34, // Version | TrafficClass | FlowID 0x2, 0x0, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV @@ -263,11 +262,10 @@ func TestComputeAuthMac(t *testing.T) { }, "epic": { optionParameter: slayers.PacketAuthOptionParams{ - SPI: slayers.PacketAuthSPI(2 ^ 21 - 1), - Algorithm: slayers.PacketAuthCMAC, - Timestamp: 0x3e8, - SequenceNumber: sn, - Auth: make([]byte, 16), + SPI: slayers.PacketAuthSPI(2 ^ 21 - 1), + Algorithm: slayers.PacketAuthCMAC, + TimestampSN: 0x060504030201, + Auth: make([]byte, 16), }, scionL: slayers.SCION{ FlowID: binary.BigEndian.Uint32([]byte{0x00, 0x00, 0x12, 0x34}), @@ -298,8 +296,9 @@ func TestComputeAuthMac(t *testing.T) { // 1. Authenticator Option Metadata 0x1d, 0xca, 0x0, 0xc, // HdrLen | Upper Layer | Upper-Layer Packet Length - 0x0, 0x0, 0x3, 0xe8, // Algorithm | Timestamp - 0x0, 0x6, 0x5, 0x4, // RSV | Sequence Number + 0x0, 0x0, // Algorithm | RSV + 0x6, 0x5, 0x4, 0x3, // Timestamp / Sequence Number + 0x2, 0x1, // 2. SCION Common Header 0x3, 0xf0, 0x12, 0x34, // Version | TrafficClass | FlowID 0x3, 0x0, 0x0, 0x0, // PathType |DT |DL |ST |SL | RSV diff --git a/pkg/spao/timestamp.go b/pkg/spao/timestamp.go index 0298340e2..5a50fc9c4 100644 --- a/pkg/spao/timestamp.go +++ b/pkg/spao/timestamp.go @@ -17,24 +17,23 @@ package spao import ( "time" + "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/private/serrors" - "github.com/scionproto/scion/pkg/private/util" ) -// RelativeTimestamp computes the relative timestamp (spaoTS) where: -// now = ts+spaoTS⋅𝑞, (where q := 6 ms and ts = info[0].Timestamp, i.e., -// the timestamp field in the first InfoField). -func RelativeTimestamp(ts uint32, now time.Time) (uint32, error) { - timestamp := now.Sub(util.SecsToTime(ts)).Milliseconds() / 6 - if timestamp >= (1 << 24) { - return 0, serrors.New("relative timestamp is bigger than 2^24-1") +// RelativeTimestamp returns the relative timestamp (RelTime) as the time diference from +// time instant t to the beginning of the drkey epoch. +func RelativeTimestamp(e drkey.Epoch, t time.Time) (uint64, error) { + relTime := t.Sub(e.NotBefore).Nanoseconds() + if relTime >= (1 << 48) { + return 0, serrors.New("relative timestamp is bigger than 2^48-1") } - return uint32(timestamp), nil + return uint64(relTime), nil } -// Time computes the time instant (then) where: -// then = ts + spaoTS⋅𝑞, (where q := 6 ms and ts = info[0].Timestamp, i.e., -// the timestamp field in the first InfoField). -func Time(ts uint32, spaoTS uint32) time.Time { - return util.SecsToTime(ts).Add(time.Millisecond * time.Duration(spaoTS) * 6) +// AbsoluteTimestamp returns the absolute timestamp (AbsTime) based on the +// relTime (Timestamp / Sequence Number field in SPAO header) and the DRKey +// information. +func AbsoluteTimestamp(e drkey.Epoch, relTime uint64) time.Time { + return e.NotBefore.Add(time.Duration(relTime)) } diff --git a/pkg/spao/timestamp_test.go b/pkg/spao/timestamp_test.go new file mode 100644 index 000000000..1872afc55 --- /dev/null +++ b/pkg/spao/timestamp_test.go @@ -0,0 +1,72 @@ +// Copyright 2022 ETH Zurich +// +// 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 spao_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/spao" + "github.com/scionproto/scion/private/drkey/drkeyutil" +) + +func TestTimestamp(t *testing.T) { + now := time.Now() + testCases := map[string]struct { + currentTime time.Time + epoch drkey.Epoch + assertErr assert.ErrorAssertionFunc + }{ + "valid": { + currentTime: now, + epoch: getEpoch(now), + assertErr: assert.NoError, + }, + "invalid": { + currentTime: now, + epoch: getEpoch(now.Add(-4 * 24 * time.Hour)), + assertErr: assert.Error, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + + rt, err := spao.RelativeTimestamp(tc.epoch, tc.currentTime) + tc.assertErr(t, err) + if err != nil { + return + } + recoveredTime := spao.AbsoluteTimestamp(tc.epoch, rt) + // XXX(JordiSubira): It seems that until testify v2 + // using assert.Equal(·) with time.Time vales will + // due to monotonic clock being drop between conversions + // https://github.com/stretchr/testify/issues/502#issuecomment-660946051 + assert.True(t, tc.currentTime.Equal(recoveredTime)) + }) + } +} + +func getEpoch(t time.Time) drkey.Epoch { + epochDuration := drkeyutil.LoadEpochDuration() + duration := int64(epochDuration / time.Second) + idx := t.Unix() / duration + begin := uint32(idx * duration) + end := begin + uint32(duration) + return drkey.NewEpoch(begin, end) +} diff --git a/private/drkey/drkeyutil/BUILD.bazel b/private/drkey/drkeyutil/BUILD.bazel new file mode 100644 index 000000000..c34f4f4c1 --- /dev/null +++ b/private/drkey/drkeyutil/BUILD.bazel @@ -0,0 +1,19 @@ +load("//tools/lint:go.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "drkey.go", + "provider.go", + ], + importpath = "github.com/scionproto/scion/private/drkey/drkeyutil", + visibility = ["//visibility:public"], + deps = [ + "//pkg/addr:go_default_library", + "//pkg/drkey:go_default_library", + "//pkg/private/serrors:go_default_library", + "//pkg/private/util:go_default_library", + "//pkg/scrypto/cppki:go_default_library", + "//pkg/spao:go_default_library", + ], +) diff --git a/private/drkey/drkeyutil/drkey.go b/private/drkey/drkeyutil/drkey.go new file mode 100644 index 000000000..31d252586 --- /dev/null +++ b/private/drkey/drkeyutil/drkey.go @@ -0,0 +1,58 @@ +// Copyright 2023 ETH Zurich +// +// 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 drkeyutil + +import ( + "os" + "time" + + "github.com/scionproto/scion/pkg/private/util" +) + +const ( + // DefaultEpochDuration is the default duration for the drkey SecretValue and derived keys + DefaultEpochDuration = 24 * time.Hour + EnvVarEpochDuration = "SCION_TESTING_DRKEY_EPOCH_DURATION" + // DefaultAcceptanceWindow is the time width for accepting incoming packets. The + // acceptance window is then computed as: + // aw := [T-a, T+a) + // where aw:= acceptance window, T := time instant and a := aw/2 + DefaultAcceptanceWindow = 5 * time.Minute + EnvVarAcceptanceWindow = "SCION_TESTING_ACCEPTANCE_WINDOW" +) + +func LoadEpochDuration() time.Duration { + s := os.Getenv(EnvVarEpochDuration) + if s == "" { + return DefaultEpochDuration + } + duration, err := util.ParseDuration(s) + if err != nil { + return DefaultEpochDuration + } + return duration +} + +func LoadAcceptanceWindow() time.Duration { + s := os.Getenv(EnvVarAcceptanceWindow) + if s == "" { + return DefaultAcceptanceWindow + } + duration, err := util.ParseDuration(s) + if err != nil { + return DefaultAcceptanceWindow + } + return duration +} diff --git a/private/drkey/drkeyutil/provider.go b/private/drkey/drkeyutil/provider.go new file mode 100644 index 000000000..f3278b166 --- /dev/null +++ b/private/drkey/drkeyutil/provider.go @@ -0,0 +1,115 @@ +// Copyright 2023 ETH Zurich +// +// 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 drkeyutil + +import ( + "time" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/scrypto/cppki" + "github.com/scionproto/scion/pkg/spao" +) + +type FakeProvider struct { + EpochDuration time.Duration + AcceptanceWindow time.Duration +} + +func (p *FakeProvider) GetASHostKey( + validTime time.Time, + _ addr.IA, + _ addr.Host, +) (drkey.ASHostKey, error) { + + duration := int64(p.EpochDuration / time.Second) + idxCurrent := validTime.Unix() / duration + epochCurrent := newEpoch(idxCurrent, duration) + return drkey.ASHostKey{ + Key: drkey.Key{}, + Epoch: epochCurrent, + }, nil +} + +func (p *FakeProvider) GetKeyWithinAcceptanceWindow( + t time.Time, + timestamp uint64, + dstIA addr.IA, + dstAddr addr.Host, +) (drkey.ASHostKey, error) { + + keys, err := p.getASHostTriple(t, dstIA, dstAddr) + if err != nil { + return drkey.ASHostKey{}, err + } + + awBegin := t.Add(-(p.AcceptanceWindow / 2)) + awEnd := t.Add(p.AcceptanceWindow / 2) + validity := cppki.Validity{ + NotBefore: awBegin, + NotAfter: awEnd, + } + + absTimePrevious := spao.AbsoluteTimestamp(keys[0].Epoch, timestamp) + absTimeCurrent := spao.AbsoluteTimestamp(keys[1].Epoch, timestamp) + absTimeNext := spao.AbsoluteTimestamp(keys[2].Epoch, timestamp) + switch { + case validity.Contains(absTimeCurrent): + return keys[1], nil + case validity.Contains(absTimePrevious): + return keys[0], nil + case validity.Contains(absTimeNext): + return keys[2], nil + default: + return drkey.ASHostKey{}, serrors.New("no absTime falls into the acceptance window", + "awBegin", awBegin, "awEnd", awEnd, "absTimePrevious", absTimePrevious, + "absTimeCurrent", absTimeCurrent, "absTimeNext", absTimeNext) + } +} + +func (p *FakeProvider) getASHostTriple( + validTime time.Time, + _ addr.IA, + _ addr.Host, +) ([]drkey.ASHostKey, error) { + + duration := int64(p.EpochDuration / time.Second) + idxCurrent := validTime.Unix() / duration + idxPrevious, idxNext := idxCurrent-1, idxCurrent+1 + epochPrevious := newEpoch(idxPrevious, duration) + epochCurrent := newEpoch(idxCurrent, duration) + epochNext := newEpoch(idxNext, duration) + return []drkey.ASHostKey{ + { + Epoch: epochPrevious, + Key: drkey.Key{}, + }, + { + Epoch: epochCurrent, + Key: drkey.Key{}, + }, + { + Epoch: epochNext, + Key: drkey.Key{}, + }, + }, nil +} + +func newEpoch(idx int64, duration int64) drkey.Epoch { + begin := uint32(idx * duration) + end := begin + uint32(duration) + return drkey.NewEpoch(begin, end) +} diff --git a/router/BUILD.bazel b/router/BUILD.bazel index 27ad3eb3e..d7ebcbc60 100644 --- a/router/BUILD.bazel +++ b/router/BUILD.bazel @@ -26,6 +26,7 @@ go_library( "//pkg/slayers/path/onehop:go_default_library", "//pkg/slayers/path/scion:go_default_library", "//pkg/spao:go_default_library", + "//private/drkey/drkeyutil:go_default_library", "//private/topology:go_default_library", "//private/underlay/conn:go_default_library", "//router/bfd:go_default_library", diff --git a/router/dataplane.go b/router/dataplane.go index d47348f9c..649d16b42 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -50,6 +50,7 @@ import ( "github.com/scionproto/scion/pkg/slayers/path/onehop" "github.com/scionproto/scion/pkg/slayers/path/scion" "github.com/scionproto/scion/pkg/spao" + "github.com/scionproto/scion/private/drkey/drkeyutil" "github.com/scionproto/scion/private/topology" underlayconn "github.com/scionproto/scion/private/underlay/conn" "github.com/scionproto/scion/router/bfd" @@ -142,7 +143,13 @@ var ( ) type drkeyProvider interface { - GetAuthKey(validTime time.Time, dstIA addr.IA, dstAddr addr.Host) (drkey.Key, error) + GetASHostKey(validTime time.Time, dstIA addr.IA, dstAddr addr.Host) (drkey.ASHostKey, error) + GetKeyWithinAcceptanceWindow( + validTime time.Time, + timestamp uint64, + dstIA addr.IA, + dstAddr addr.Host, + ) (drkey.ASHostKey, error) } type scmpError struct { @@ -827,9 +834,13 @@ func newPacketProcessor(d *DataPlane) *scionPacketProcessor { drkeyInput: make([]byte, spao.MACBufferSize), }, // TODO(JordiSubira): Replace this with a useful implementation. - drkeyProvider: &fakeProvider{}, - optAuth: slayers.PacketAuthOption{EndToEndOption: new(slayers.EndToEndOption)}, - validAuthBuf: make([]byte, 16), + + drkeyProvider: &drkeyutil.FakeProvider{ + EpochDuration: drkeyutil.LoadEpochDuration(), + AcceptanceWindow: drkeyutil.LoadAcceptanceWindow(), + }, + optAuth: slayers.PacketAuthOption{EndToEndOption: new(slayers.EndToEndOption)}, + validAuthBuf: make([]byte, 16), } p.scionLayer.RecyclePaths() return p @@ -1943,7 +1954,7 @@ func (p *scionPacketProcessor) prepareSCMP( // if SCMPTypeTracerouteReply to create the response. needsAuth := cause != nil || (scmpH.TypeCode.Type() == slayers.SCMPTypeTracerouteReply && - p.hasValidAuth()) + p.hasValidAuth(time.Now())) var quote []byte if cause != nil { @@ -1988,11 +1999,11 @@ func (p *scionPacketProcessor) prepareSCMP( now := time.Now() // srcA == scionL.DstAddr - key, err := p.drkeyProvider.GetAuthKey(now, scionL.DstIA, srcA) + key, err := p.drkeyProvider.GetASHostKey(now, scionL.DstIA, srcA) if err != nil { return nil, serrors.Wrap(cannotRoute, err, "details", "retrieving DRKey") } - if err := p.resetSPAOMetadata(now); err != nil { + if err := p.resetSPAOMetadata(key, now); err != nil { return nil, serrors.Wrap(cannotRoute, err, "details", "resetting SPAO header") } @@ -2000,7 +2011,7 @@ func (p *scionPacketProcessor) prepareSCMP( e2e.NextHdr = slayers.L4SCMP _, err = spao.ComputeAuthCMAC( spao.MACInput{ - Key: key[:], + Key: key.Key[:], Header: p.optAuth, ScionLayer: &scionL, PldType: slayers.L4SCMP, @@ -2025,43 +2036,30 @@ func (p *scionPacketProcessor) prepareSCMP( return p.buffer.Bytes(), scmpError{TypeCode: scmpH.TypeCode, Cause: cause} } -func (p *scionPacketProcessor) resetSPAOMetadata(now time.Time) error { +func (p *scionPacketProcessor) resetSPAOMetadata(key drkey.ASHostKey, now time.Time) error { // For creating SCMP responses we use sender side. dir := slayers.PacketAuthSenderSide - // TODO(JordiSubira): We assume the later epoch at the moment. - // If the authentication stems from an authenticated request, we want to use - // the same key as the one used by the request sender. - epoch := slayers.PacketAuthLater drkeyType := slayers.PacketAuthASHost - spi, err := slayers.MakePacketAuthSPIDRKey(uint16(drkey.SCMP), drkeyType, dir, epoch) - if err != nil { - return err - } - - firstInfo, err := p.path.GetInfoField(0) + spi, err := slayers.MakePacketAuthSPIDRKey(uint16(drkey.SCMP), drkeyType, dir) if err != nil { return err } - timestamp, err := spao.RelativeTimestamp(firstInfo.Timestamp, now) + timestamp, err := spao.RelativeTimestamp(key.Epoch, now) if err != nil { return err } - // XXX(JordiSubira): Assume that send rate is low so that combination - // with timestamp is always unique - sn := uint32(0) return p.optAuth.Reset(slayers.PacketAuthOptionParams{ - SPI: spi, - Algorithm: slayers.PacketAuthCMAC, - Timestamp: timestamp, - SequenceNumber: sn, - Auth: zeroBuffer, + SPI: spi, + Algorithm: slayers.PacketAuthCMAC, + TimestampSN: timestamp, + Auth: zeroBuffer, }) } -func (p *scionPacketProcessor) hasValidAuth() bool { +func (p *scionPacketProcessor) hasValidAuth(t time.Time) bool { // Check if e2eLayer was parsed for this packet if !p.lastLayer.CanDecode().Contains(slayers.LayerTypeEndToEndExtn) { return false @@ -2083,25 +2081,27 @@ func (p *scionPacketProcessor) hasValidAuth() bool { return false } // Computing authField - firstInfo, err := p.path.GetInfoField(0) - if err != nil { - return false - } - then := spao.Time(firstInfo.Timestamp, authOption.Timestamp()) + // the sender should have used the receiver side key, i.e., K_{localIA-remoteIA:remoteHost} + // where remoteIA == p.scionLayer.SrcIA and remoteHost == srcAddr + // (for the incoming packet). srcAddr, err := p.scionLayer.SrcAddr() if err != nil { return false } - // the sender should have used the receiver side key, i.e., K_{localIA-remoteIA:remoteHost} - // where remoteIA == p.scionLayer.SrcIA and remoteHost == srcAddr - // (for the incoming packet). - key, err := p.drkeyProvider.GetAuthKey(then, p.scionLayer.SrcIA, srcAddr) + key, err := p.drkeyProvider.GetKeyWithinAcceptanceWindow( + t, + authOption.TimestampSN(), + p.scionLayer.SrcIA, + srcAddr, + ) if err != nil { + log.Debug("Selecting key to authenticate the incoming packet", "err", err) return false } + _, err = spao.ComputeAuthCMAC( spao.MACInput{ - Key: key[:], + Key: key.Key[:], Header: authOption, ScionLayer: &p.scionLayer, PldType: slayers.L4SCMP, @@ -2216,13 +2216,3 @@ func serviceMetricLabels(localIA addr.IA, svc addr.SVC) prometheus.Labels { "service": svc.BaseString(), } } - -type fakeProvider struct{} - -func (p *fakeProvider) GetAuthKey( - _ time.Time, - _ addr.IA, - _ addr.Host, -) (drkey.Key, error) { - return drkey.Key{}, nil -} diff --git a/tools/braccept/cases/BUILD.bazel b/tools/braccept/cases/BUILD.bazel index 30cb91f47..c856fe21d 100644 --- a/tools/braccept/cases/BUILD.bazel +++ b/tools/braccept/cases/BUILD.bazel @@ -42,6 +42,7 @@ go_library( "//pkg/slayers/path/onehop:go_default_library", "//pkg/slayers/path/scion:go_default_library", "//pkg/spao:go_default_library", + "//private/drkey/drkeyutil:go_default_library", "//tools/braccept/runner:go_default_library", "@com_github_google_gopacket//:go_default_library", "@com_github_google_gopacket//layers:go_default_library", diff --git a/tools/braccept/cases/scmp.go b/tools/braccept/cases/scmp.go index 28f6d8c6f..d90b480b3 100644 --- a/tools/braccept/cases/scmp.go +++ b/tools/braccept/cases/scmp.go @@ -51,11 +51,10 @@ func normalizePacketAuthOption(pkt gopacket.Packet) { 0, 0, 0, 0, 0, 0, 0, 0} _ = optAuth.Reset(slayers.PacketAuthOptionParams{ - SPI: spi, - Algorithm: alg, - Timestamp: uint32(0), - SequenceNumber: uint32(0), - Auth: auth, + SPI: spi, + Algorithm: alg, + TimestampSN: uint64(0), + Auth: auth, }) } @@ -64,17 +63,15 @@ func normalizedSCMPPacketAuthEndToEndExtn() *slayers.EndToEndExtn { uint16(drkey.SCMP), slayers.PacketAuthASHost, slayers.PacketAuthSenderSide, - slayers.PacketAuthLater, ) if err != nil { panic(err) } packAuthOpt, err := slayers.NewPacketAuthOption(slayers.PacketAuthOptionParams{ - SPI: spi, - Algorithm: slayers.PacketAuthCMAC, - Timestamp: uint32(0), - SequenceNumber: uint32(0), - Auth: make([]byte, 16), + SPI: spi, + Algorithm: slayers.PacketAuthCMAC, + TimestampSN: uint64(0), + Auth: make([]byte, 16), }) if err != nil { panic(err) diff --git a/tools/braccept/cases/scmp_expired_hop.go b/tools/braccept/cases/scmp_expired_hop.go index 02a886cea..d8b645cff 100644 --- a/tools/braccept/cases/scmp_expired_hop.go +++ b/tools/braccept/cases/scmp_expired_hop.go @@ -119,118 +119,9 @@ func SCMPExpiredHop(artifactsDir string, mac hash.Hash) runner.Case { scionudp.DstPort = 40222 scionudp.SetNetworkLayerForChecksum(scionL) - payload := []byte("actualpayloadbytes") - // Prepare input packet - input := gopacket.NewSerializeBuffer() - if err := gopacket.SerializeLayers(input, options, - ethernet, ip, udp, scionL, scionudp, gopacket.Payload(payload), - ); err != nil { - panic(err) - } - - // Prepare want packet - - return runner.Case{ - Name: "SCMPExpiredHop", - WriteTo: "veth_131_host", - ReadFrom: "veth_131_host", - Input: input.Bytes(), - Want: nil, - StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHop"), - NormalizePacket: scmpNormalizePacket, - } -} - -// SCMPExpiredHopMessageBack tests a packet with an expired hop field. The relative timestamp -// can be encoded in the SPAO header and sent back to the src. -func SCMPExpiredHopMessageBack(artifactsDir string, mac hash.Hash) runner.Case { - options := gopacket.SerializeOptions{ - FixLengths: true, - ComputeChecksums: true, - } - - // Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4 - ethernet := &layers.Ethernet{ - SrcMAC: net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0xbe, 0xef}, - DstMAC: net.HardwareAddr{0xf0, 0x0d, 0xca, 0xfe, 0x00, 0x13}, - EthernetType: layers.EthernetTypeIPv4, - } - // IP4: Src=192.168.13.3 Dst=192.168.13.2 NextHdr=UDP Flags=DF - ip := &layers.IPv4{ - Version: 4, - IHL: 5, - TTL: 64, - SrcIP: net.IP{192, 168, 13, 3}, - DstIP: net.IP{192, 168, 13, 2}, - Protocol: layers.IPProtocolUDP, - Flags: layers.IPv4DontFragment, - } - // UDP: Src=40000 Dst=50000 - udp := &layers.UDP{ - SrcPort: layers.UDPPort(40000), - DstPort: layers.UDPPort(50000), - } - _ = udp.SetNetworkLayerForChecksum(ip) - - // pkt0.ParsePacket(` - // SCION: NextHdr=UDP CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=IPv4 - // ADDR: SrcIA=1-ff00:0:3 Src=174.16.3.1 DstIA=1-ff00:0:4 Dst=174.16.4.1 - // IF_1: ISD=1 Hops=3 Flags=ConsDir - // HF_1: ConsIngress=0 ConsEgress=311 - // HF_2: ConsIngress=131 ConsEgress=141 - // HF_3: ConsIngress=411 ConsEgress=0 - // UDP_1: Src=40111 Dst=40222 - // `) - sp := &scion.Decoded{ - Base: scion.Base{ - PathMeta: scion.MetaHdr{ - CurrHF: 1, - SegLen: [3]uint8{3, 0, 0}, - }, - NumINF: 1, - NumHops: 3, - }, - InfoFields: []path.InfoField{ - { - SegID: 0x111, - ConsDir: true, - Timestamp: util.TimeToSecs(time.Now().Add(-6 * time.Minute)), - }, - }, - HopFields: []path.HopField{ - {ConsIngress: 0, ConsEgress: 311}, - {ConsIngress: 131, ConsEgress: 141}, - {ConsIngress: 411, ConsEgress: 0}, - }, - } - sp.HopFields[1].Mac = path.MAC(mac, sp.InfoFields[0], sp.HopFields[1], nil) - - scionL := &slayers.SCION{ - Version: 0, - TrafficClass: 0xb8, - FlowID: 0xdead, - NextHdr: slayers.L4UDP, - PathType: scion.PathType, - SrcIA: xtest.MustParseIA("1-ff00:0:3"), - DstIA: xtest.MustParseIA("1-ff00:0:4"), - Path: sp, - } - srcA := addr.MustParseHost("172.16.3.1") - if err := scionL.SetSrcAddr(srcA); err != nil { - panic(err) - } - if err := scionL.SetDstAddr(addr.MustParseHost("174.16.4.1")); err != nil { - panic(err) - } - - scionudp := &slayers.UDP{} - scionudp.SrcPort = 40111 - scionudp.DstPort = 40222 - scionudp.SetNetworkLayerForChecksum(scionL) - - payload := []byte("actualpayloadbytes") pointer := slayers.CmnHdrLen + scionL.AddrHdrLen() + (4 + 8*sp.NumINF + 12*int(sp.PathMeta.CurrHF)) + payload := []byte("actualpayloadbytes") // Prepare input packet input := gopacket.NewSerializeBuffer() @@ -291,20 +182,20 @@ func SCMPExpiredHopMessageBack(artifactsDir string, mac hash.Hash) runner.Case { } return runner.Case{ - Name: "SCMPExpiredHopMessageBack", + Name: "SCMPExpiredHop", WriteTo: "veth_131_host", ReadFrom: "veth_131_host", Input: input.Bytes(), Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopMessageBack"), + StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHop"), NormalizePacket: scmpNormalizePacket, } } -// SCMPExpiredHopAfterXoverMessageBack tests a packet with an expired hop field after an +// SCMPExpiredHopAfterXover tests a packet with an expired hop field after an // x-over. The relative timestamp can be encoded // in the SPAO header and sent back to the src. -func SCMPExpiredHopAfterXoverMessageBack(artifactsDir string, mac hash.Hash) runner.Case { +func SCMPExpiredHopAfterXover(artifactsDir string, mac hash.Hash) runner.Case { options := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, @@ -470,20 +361,20 @@ func SCMPExpiredHopAfterXoverMessageBack(artifactsDir string, mac hash.Hash) run } return runner.Case{ - Name: "SCMPExpiredHopAfterXoverMessageBack", + Name: "SCMPExpiredHopAfterXover", WriteTo: "veth_151_host", ReadFrom: "veth_151_host", Input: input.Bytes(), Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverMessageBack"), + StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXover"), NormalizePacket: scmpNormalizePacket, } } -// SCMPExpiredHopAfterXoverConsDirMessageBack tests a packet with an expired hop field after an +// SCMPExpiredHopAfterXoverConsDir tests a packet with an expired hop field after an // x-over. The relative timestamp can be encoded // in the SPAO header and sent back to the src. -func SCMPExpiredHopAfterXoverConsDirMessageBack(artifactsDir string, mac hash.Hash) runner.Case { +func SCMPExpiredHopAfterXoverConsDir(artifactsDir string, mac hash.Hash) runner.Case { options := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, @@ -646,12 +537,12 @@ func SCMPExpiredHopAfterXoverConsDirMessageBack(artifactsDir string, mac hash.Ha } return runner.Case{ - Name: "SCMPExpiredHopAfterXoverConsDirMessageBack", + Name: "SCMPExpiredHopAfterXoverConsDir", WriteTo: "veth_151_host", ReadFrom: "veth_151_host", Input: input.Bytes(), Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverConsDirMessageBack"), + StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverConsDir"), NormalizePacket: scmpNormalizePacket, } } @@ -660,7 +551,7 @@ func SCMPExpiredHopAfterXoverConsDirMessageBack(artifactsDir string, mac hash.Ha // field after an x-over received from an internal router. The expired path // segment is against construction direction. The relative timestamp can be encoded // in the SPAO header and sent back to the src. -func SCMPExpiredHopAfterXoverInternalMessageBack(artifactsDir string, mac hash.Hash) runner.Case { +func SCMPExpiredHopAfterXoverInternal(artifactsDir string, mac hash.Hash) runner.Case { options := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, @@ -816,22 +707,22 @@ func SCMPExpiredHopAfterXoverInternalMessageBack(artifactsDir string, mac hash.H } return runner.Case{ - Name: "SCMPExpiredHopAfterXoverInternalMessageBack", + Name: "SCMPExpiredHopAfterXoverInternal", WriteTo: "veth_int_host", ReadFrom: "veth_int_host", Input: input.Bytes(), Want: want.Bytes(), - StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverInternalMessageBack"), + StoreDir: filepath.Join(artifactsDir, "SCMPExpiredHopAfterXoverInternal"), NormalizePacket: scmpNormalizePacket, } } -// SCMPExpiredHopAfterXoverInternalConsDirMessageBack tests a packet with an expired hop +// SCMPExpiredHopAfterXoverInternalConsDir tests a packet with an expired hop // field after an x-over received from an internal router. The expired path // segment is in construction direction. The expired path // segment is against construction direction. The relative timestamp can be encoded // in the SPAO header and sent back to the src. -func SCMPExpiredHopAfterXoverInternalConsDirMessageBack( +func SCMPExpiredHopAfterXoverInternalConsDir( artifactsDir string, mac hash.Hash, ) runner.Case { @@ -987,14 +878,14 @@ func SCMPExpiredHopAfterXoverInternalConsDirMessageBack( } return runner.Case{ - Name: "SCMPExpiredHopAfterXoverInternalConsDirMessageBack", + Name: "SCMPExpiredHopAfterXoverInternalConsDir", WriteTo: "veth_int_host", ReadFrom: "veth_int_host", Input: input.Bytes(), Want: want.Bytes(), StoreDir: filepath.Join( artifactsDir, - "SCMPExpiredHopAfterXoverInternalConsDirMessageBack", + "SCMPExpiredHopAfterXoverInternalConsDir", ), NormalizePacket: scmpNormalizePacket, } diff --git a/tools/braccept/cases/scmp_invalid_mac.go b/tools/braccept/cases/scmp_invalid_mac.go index ce94c1c20..3a5fbd7f5 100644 --- a/tools/braccept/cases/scmp_invalid_mac.go +++ b/tools/braccept/cases/scmp_invalid_mac.go @@ -306,11 +306,10 @@ func SCMPBadMACInternal(artifactsDir string, mac hash.Hash) runner.Case { panic(err) } - p, err := sp.Reverse() + _, err := sp.Reverse() if err != nil { panic(err) } - sp = p.(*scion.Decoded) scionL.NextHdr = slayers.End2EndClass e2e := normalizedSCMPPacketAuthEndToEndExtn() e2e.NextHdr = slayers.L4SCMP diff --git a/tools/braccept/cases/scmp_traceroute.go b/tools/braccept/cases/scmp_traceroute.go index 6242efe1e..b405ce04c 100644 --- a/tools/braccept/cases/scmp_traceroute.go +++ b/tools/braccept/cases/scmp_traceroute.go @@ -31,6 +31,7 @@ import ( "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/pkg/slayers/path/scion" "github.com/scionproto/scion/pkg/spao" + "github.com/scionproto/scion/private/drkey/drkeyutil" "github.com/scionproto/scion/tools/braccept/runner" ) @@ -256,8 +257,22 @@ func SCMPTracerouteIngressWithSPAO(artifactsDir string, mac hash.Hash) runner.Ca } e2e := &slayers.EndToEndExtn{} + + sendTime := time.Now() + key, err := (&drkeyutil.FakeProvider{ + EpochDuration: drkeyutil.LoadEpochDuration(), + AcceptanceWindow: drkeyutil.LoadAcceptanceWindow(), + }).GetASHostKey(sendTime, xtest.MustParseIA("1-ff00:0:4"), srcA) + if err != nil { + panic(err) + } + timestamp, err := spao.RelativeTimestamp(key.Epoch, sendTime) + if err != nil { + panic(err) + } optAuth, err := slayers.NewPacketAuthOption(slayers.PacketAuthOptionParams{ - Auth: make([]byte, 16), + TimestampSN: timestamp, + Auth: make([]byte, 16), }) if err != nil { panic(err) @@ -279,7 +294,7 @@ func SCMPTracerouteIngressWithSPAO(artifactsDir string, mac hash.Hash) runner.Ca } _, err = spao.ComputeAuthCMAC( spao.MACInput{ - Key: (&drkey.Key{})[:], + Key: key.Key[:], Header: optAuth, ScionLayer: scionL, PldType: slayers.L4SCMP, @@ -331,17 +346,15 @@ func SCMPTracerouteIngressWithSPAO(artifactsDir string, mac hash.Hash) runner.Ca uint16(drkey.SCMP), slayers.PacketAuthASHost, slayers.PacketAuthSenderSide, - slayers.PacketAuthLater, ) if err != nil { panic(err) } packAuthOpt, err := slayers.NewPacketAuthOption(slayers.PacketAuthOptionParams{ - SPI: spi, - Algorithm: slayers.PacketAuthCMAC, - Timestamp: uint32(0), - SequenceNumber: uint32(0), - Auth: make([]byte, 16), + SPI: spi, + Algorithm: slayers.PacketAuthCMAC, + TimestampSN: uint64(0), + Auth: make([]byte, 16), }) if err != nil { panic(err) @@ -1068,11 +1081,10 @@ func SCMPTracerouteInternal(artifactsDir string, mac hash.Hash) runner.Case { } sp.HopFields[0].EgressRouterAlert = false - p, err := sp.Reverse() + _, err := sp.Reverse() if err != nil { panic(err) } - sp = p.(*scion.Decoded) scionL.NextHdr = slayers.L4SCMP scmpH = &slayers.SCMP{ TypeCode: slayers.CreateSCMPTypeCode(slayers.SCMPTypeTracerouteReply, 0), diff --git a/tools/braccept/main.go b/tools/braccept/main.go index fc27bf7af..e36d9de30 100644 --- a/tools/braccept/main.go +++ b/tools/braccept/main.go @@ -93,12 +93,11 @@ func realMain() int { cases.SCMPDestinationUnreachable(artifactsDir, hfMAC), cases.SCMPBadMAC(artifactsDir, hfMAC), cases.SCMPBadMACInternal(artifactsDir, hfMAC), - cases.SCMPExpiredHopAfterXoverMessageBack(artifactsDir, hfMAC), - cases.SCMPExpiredHopAfterXoverConsDirMessageBack(artifactsDir, hfMAC), - cases.SCMPExpiredHopAfterXoverInternalMessageBack(artifactsDir, hfMAC), - cases.SCMPExpiredHopAfterXoverInternalConsDirMessageBack(artifactsDir, hfMAC), + cases.SCMPExpiredHopAfterXover(artifactsDir, hfMAC), + cases.SCMPExpiredHopAfterXoverConsDir(artifactsDir, hfMAC), + cases.SCMPExpiredHopAfterXoverInternal(artifactsDir, hfMAC), + cases.SCMPExpiredHopAfterXoverInternalConsDir(artifactsDir, hfMAC), cases.SCMPExpiredHop(artifactsDir, hfMAC), - cases.SCMPExpiredHopMessageBack(artifactsDir, hfMAC), cases.SCMPChildToParentXover(artifactsDir, hfMAC), cases.SCMPParentToChildXover(artifactsDir, hfMAC), cases.SCMPParentToParentXover(artifactsDir, hfMAC), From c5043518fde45890b0d957d2878185c6ef614157 Mon Sep 17 00:00:00 2001 From: JordiSubira Date: Tue, 26 Sep 2023 18:41:48 +0200 Subject: [PATCH 059/255] doc: update timestamp spec (#4300) This PR updates the Timestamp definition in the SPAO specification. This update follows the discussion in #4062, making the Timestamp relative to the DRKey Epoch for DRKey SPI associations. --- doc/cryptography/drkey.rst | 23 ++-- doc/manuals/router.rst | 8 ++ doc/protocols/authenticator-option.rst | 148 +++++++++++++++---------- 3 files changed, 113 insertions(+), 66 deletions(-) diff --git a/doc/cryptography/drkey.rst b/doc/cryptography/drkey.rst index 36c63c486..23b10db46 100644 --- a/doc/cryptography/drkey.rst +++ b/doc/cryptography/drkey.rst @@ -28,7 +28,7 @@ to derive keys in the hierarchy from top to bottom. The first secret in the hierarchy (:math:`SV_A`) is derived from a long-term ``master_secret``, using a key derivation function. For the rest of the derivations, DRKey utilizes pseudorandom functions, which are more efficient. -Informally, key derivation functions output a cryptographic key indistingushible from +Informally, key derivation functions output a cryptographic key indistinguishable from a random key if the secret is unknown for the attacker. In contrast, the security of pseudorandom functions relies on the input being a uniformly random secret. @@ -134,7 +134,7 @@ Protocol-specific derivation - host-host key (Level 3) The SV computation is local, thus the AS is free to compute it as desired as long as -it outputs a cryptographic key indistingushible from a random key for an attacker. +it outputs a cryptographic key indistinguishable from a random key for an attacker. We suggest to use the *PBKDF2* as KDF function and set ``input`` to: ``input = "len(master_secret) || master_secret || protocol || epoch_begin || epoch_end"``. @@ -216,6 +216,8 @@ except for the host address whose length is prepended. Key Validity time ================= +.. _drkey-epoch: + Epochs ------ An epoch is an interval between a starting and ending point in time. The epoch @@ -229,10 +231,15 @@ Defining a reasonable lower bound for the epoch length used in DRKey is necessary to avoid nonsensical scenarios. This value is globally set to 6 minutes. +The upper bound for the epoch length is defined to 3 days, looking for a trade-off +between efficiency and security. + .. note:: - This lower bound might be changed in the future in case a more suitable - value is found. + These bounds might be changed in the future in case a more suitable + values are found. + +.. _drkey-grace: Grace period ------------ @@ -248,7 +255,7 @@ Prefetching period ------------------ ASes will be allowed to prefetch keys some time before the key for the current epoch expires. This period must be long enough to allow every remote AS to attempt the key prefetching -enough times to be succesful even in the presence of failures. However, this period +enough times to be successful even in the presence of failures. However, this period should not be too long, since the issuer AS is not assumed to carry out any changes once it has issued keys for a given epoch (e.g. modifying SV epoch duration, rotating the master secret, etc.). @@ -270,8 +277,10 @@ The subject-AS on the slow side (i.e. the AS requesting the key) will establish the issuer-AS on the fast side (i.e. the AS serving the key). Both parties identify each other by using the CP-PKI infrastructure. -The Level 1 key request message contains the ``validTime`` for which the key must be active -and the ``protocol_id``. The Level 1 key response includes the symmetric key along with the epoch +The Level 1 key request message contains the ``validTime`` that specifies for what time the requested +key must be valid (it implicitly specifies the epoch for which the key will be valid) +and the ``protocol_id``. +The Level 1 key response includes the symmetric key along with the epoch for which this key will be valid. The ``protocol_id`` is either set to ``GENERIC = 0`` to request Lvl1 keys that will be derived according to diff --git a/doc/manuals/router.rst b/doc/manuals/router.rst index 8ad652640..cd5f97b57 100644 --- a/doc/manuals/router.rst +++ b/doc/manuals/router.rst @@ -88,6 +88,14 @@ Environment Variables Same applicability as above; can be overridden for specific inter-AS BFD sessions with :option:`bfd.required_min_rx_interval `. +.. envvar:: SCION_TESTING_DRKEY_EPOCH_DURATION + + Defines the global DRKey :ref:`Epoch` duration that the border router + assumes. + +.. envvar:: SCION_TESTING_ACCEPTANCE_WINDOW + + Defines the acceptance window following the :ref:`SPAO specification`. Configuration ============= diff --git a/doc/protocols/authenticator-option.rst b/doc/protocols/authenticator-option.rst index b7af39fc0..077069603 100644 --- a/doc/protocols/authenticator-option.rst +++ b/doc/protocols/authenticator-option.rst @@ -35,9 +35,9 @@ Alignment requirement: 4n + 2:: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Security Parameter Index | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Algorithm | Timestamp | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | RSV | Sequence Number | + | Algorithm | RSV | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + | Timestamp / Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Authenticator ... | | | @@ -49,50 +49,41 @@ OptDataLen Unsigned 8-bit integer denoting the length in bytes of the full option data (12 + length of Authenticator). The length depends on algorithm used. -Timestamp: - Unsigned 24-bit integer timestamp. - The timestamp expressed by the value of this field is relative to the - `Timestamp` of the first :ref:`Info Field` of the - SCION Path. - The timestamp has a granularity of - - .. math:: - q := \left\lceil\left( - \frac{24 \times 60 \times 60 \times 10^3} - {2^{24}} - \right)\right\rceil ms - = 6 ms.\\ - - and the absolute Unix time expressed by this Timestamp field is - - .. math:: - \mathrm{info[0].Timestamp} + \mathrm{Timestamp} \cdot q - - The Timestamp field can be used for replay detection by the receiver. - The receiver SHOULD drop packets with timestamps outside of a locally chosen +Timestamp / Sequence Number: + Unsigned 48-bit integer value. + The Timestamp / Sequence Number field contains a value for each packet that + can be used for replay detection by the receiver. + The detailed interpretation of the Timestamp / Sequence Number field depends on the :ref:`SPI `. + + When used with a DRKey :ref:`SPI `, the field represents a relative Timestamp (*Ts*), + counting the nanoseconds since the starting time of the associated DRKey :ref:`Epoch`. + (See :ref:`Appendix` for a more detailed explanation about the field interpretation). + The timestamp MAY be used to compute the absolute time (*AbsTime*) value, + which corresponds to the time when the packet was sent. + The section :ref:`Absolute time derivation` describes the derivation of *AbsTime* and + the associated DRKey. + + The receiver SHOULD drop packets with *AbsTime* outside of a locally chosen range around the current time. -Sequence Number: - Unsigned 24-bit sequence number. - This field can be used for replay detection by the receiver. - - When used with a :ref:`SPI ` referring to an established - security association, this is used as a wrapping counter and replay detection - is based on sliding window of expected counter values. - This use case is not specified in detail here. Extending this specification - in the future will closely follow [`RFC 4302 `_]. - - When used with :ref:`spao-spi-drkey`, this field is used together with the - timestamp field to provide a unique identifier for a packet. - The sender can arbitrarily choose this value, but it SHOULD ensure - the uniqueness of the combination of timestamp and sequence number. - For example, the value can be chosen based on a counter, randomly or even as - a constant, provided that the send rate is low enough. - The receiver SHOULD drop packets with duplicate + The sender SHOULD ensure the uniqueness of the absolute time (*AbsTime*) per identical packet. + The receiver will use the *AbsTime* for replay detection and, thus, + it SHOULD drop identical packets, i.e. packets with a duplicate: .. math:: - (\mathrm{Source\ Address, info[0].Timestamp, Timestamp, Sequence\ Number}) + (\mathrm{SRC\ ISD, SRC\ AS, SrcHostAddr, Authenticator}) + + .. note:: + In other words, the duplicate suppression would happen within the + acceptance windows considering identical values for the Authenticator field, which is + computed based on packet contents, such as the Timestamp (used to derived the *AbsTime*) + and the upper layer payload + (see the section :ref:`Authenticated Data`). + When used with a non-DRKey :ref:`SPI `, this field is used as + a wrapping counter and replay detection is based on sliding window of expected counter values. + This use case is not specified in detail here. Extending this specification + in the future will closely follow [`RFC 4302 `_]. Security Parameter Index (SPI) 32-bit identifier for the key used for this authentication option. @@ -137,7 +128,7 @@ DRKey 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | 0 |R R T D E| Protocol Identifier | + | 0 |R R R T D| Protocol Identifier | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ R @@ -154,17 +145,48 @@ D * ``0``: sender-side key derivation * ``1``: receiver-side key derivation -E - Epoch. Specifies the key epoch. The time specified by the Timestamp field is - used to look up the relevant candidate epochs. At all times, at most two key - epochs can be active; this field distinguishes between these two candidates. - - * ``0``: the active epoch with later start time - * ``1``: the active epoch with earlier start time Protocol Identifier 16-bit protocol identifier. Note that 0 is a reserved protocol number and cannot occur here. +.. _spao-absTime: + +Absolute time and DRKey selection +================================= + +This section proposes an implementation method to find out the Security Association from the +SPAO metadata information, i.e., to select the DRKey to authenticate the packet. + +Firstly, the receiver entity defines an *acceptance window*. +An *acceptance window* (aw) is a time range of width *a* around the receiver's current time *T*, +i.e.,: + +:math:`aw := [T-a/2, T+a/2)` + + +[i] The acceptance window is equal or smaller than the minimum DRKey epoch length. + +The receiver entity derives the absolute timestamp and selects the associated DRKey by: + +1. Given a time instant *T*, considering: + + - Epoch :math:`E_{i}` as the one whose time range includes *T*. + - Epoch :math:`E_{i-1}` as the prior epoch to :math:`E_{i}`. + - Epoch :math:`E_{i+1}` as the subsequent epoch to :math:`E_{i}`. + +2. Adding the relative timestamp (*RelTime*) (the one in :ref:`SPAO Header`) to + the start time for :math:`E_{i-1}`, :math:`E_{i}` and :math:`E_{i+1}`, + computing the respective *absolute times* (*AbsTime*): + :math:`at_{i-1}`, :math:`at_{i}` and :math:`at_{i+1}`. +3. Given [i] at most one *absolute time* will be within *aw*. +4. The candidate DRKey is the key whose epoch is associated to *AbsTime*, + e.g., if *AbsTime* is :math:`at_{i-1}` the key belonging to :math:`E_{i-1}`. + +Note that :math:`at_{i-1}` might, for instance be within the :ref:`Grace period`, i.e., +overlapping at :math:`E_{i}`. Nevertheless, due to [i] we can unambiguously distinguish it. + + +.. _authenticated-data: Authenticated Data ================== @@ -196,9 +218,9 @@ The input for the MAC is the concatenation of the following items: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | HdrLen | Upper Layer | Upper-Layer Packet Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Algorithm | Timestamp | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | RSV | Sequence Number | + | Algorithm | RSV | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + | Timestamp / Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ HdrLen @@ -364,17 +386,15 @@ It is visible from the metadata whether the addresses are to be skipped from the MAC input, as discussed above, so that also in this case no length extension attacks are possible. +.. _spao-appendix: Appendix: Design Rationale ========================== The following goals/constraints led to this design: -- include a timestamp / sequence number to uniquely identify packets of the - entire lifetime of a SCION path (24h). +- include a timestamp / sequence number to uniquely identify packets. - - with high rates of packets (>1Gpps) we seem to need about 37 bit (~5bytes) - for uniqueness - timestamp should be accurate enough to allow dropping obviously old packets - sequence number should be long enough to allow sliding window replay suppression like in IPSec @@ -385,14 +405,24 @@ The following goals/constraints led to this design: - reasonable field alignment with little padding with 4n + 2 option alignment (to avoid padding before first option) -- 2 AES blocks or fewer for lightning filter use case (SHA1-AES-CBC with DRKey) +- 2 AES blocks or fewer for LightningFilter use case (SHA1-AES-CBC with DRKey) - Require as little copying as possible to check MAC in this use case. Hash directly following the option. - this does not appear to work with less than 3 rows. We use the available - room to make the timestamp and sequence number 3 bytes each and leave one + room to make a 48-bit Timestamp / Sequence Number field and leave one reserved byte for future extensions (e.g. flags or extended timestamp or sequence number). The SPI comes first as we don't need to include it in the MAC computation and don't want it between the other fields and the SHA1 hash. + +- When the Timestamp / Sequence Number field is used with DRKey SPI, the 48-bits in the field allow to + cover the maximum DRKey epoch length plus the :ref:`Grace period` + with granularity of 1 nanosecond, since: + + .. math:: + (3 \times 24 \times 60 \times 60 + 5) \times 10^9 < {2^{48}} + +- When the Timestamp / Sequence Number field is used with DRKey SPI, the application can use a clock that is less + accurate than 1 nanosecond and fill out the less significant bits with a counter. From b4a20118b05e5bb9e385f8ba13e0a7aad8d8dc36 Mon Sep 17 00:00:00 2001 From: rohrerj <26304001+rohrerj@users.noreply.github.com> Date: Thu, 28 Sep 2023 15:00:07 +0200 Subject: [PATCH 060/255] router: slow-path in async packet processing (#4383) Add a low-priority slow path for special case packet handling, in particular SCMP errors and traceroutes, for the the asynchronous packet processing pipeline in the router added in #4351. This is implementation part three of three described in the design document (#4339, doc/dev/design/BorderRouter.rst). Closes #4334 --- doc/manuals/router.rst | 4 +- router/dataplane.go | 586 ++++++++++++++++++++---------- router/dataplane_internal_test.go | 144 +++++++- router/dataplane_test.go | 90 +---- router/export_test.go | 2 +- 5 files changed, 545 insertions(+), 281 deletions(-) diff --git a/doc/manuals/router.rst b/doc/manuals/router.rst index cd5f97b57..6427ab616 100644 --- a/doc/manuals/router.rst +++ b/doc/manuals/router.rst @@ -160,8 +160,8 @@ considers the following options. .. option:: router.num_slow_processors = (Default: 1) - Number of goroutines started for the slow-path processing. This feature will be implemented soon. Currently - this setting has no effect. + Number of goroutines started for the slow-path processing which includes all SCMP traffic and traceroutes. + A minimum of 1 slow-path processor is required. .. option:: router.batch_size = (Default: 256) diff --git a/router/dataplane.go b/router/dataplane.go index 649d16b42..57b533da4 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -118,25 +118,31 @@ type DataPlane struct { } var ( - alreadySet = serrors.New("already set") - invalidSrcIA = serrors.New("invalid source ISD-AS") - invalidDstIA = serrors.New("invalid destination ISD-AS") - invalidSrcAddrForTransit = serrors.New("invalid source address for transit pkt") - cannotRoute = serrors.New("cannot route, dropping pkt") - emptyValue = serrors.New("empty value") - malformedPath = serrors.New("malformed path content") - modifyExisting = serrors.New("modifying a running dataplane is not allowed") - noSVCBackend = serrors.New("cannot find internal IP for the SVC") - unsupportedPathType = serrors.New("unsupported path type") - unsupportedPathTypeNextHeader = serrors.New("unsupported combination") - noBFDSessionFound = serrors.New("no BFD sessions was found") - noBFDSessionConfigured = serrors.New("no BFD sessions have been configured") - errBFDDisabled = serrors.New("BFD is disabled") - errPeeringEmptySeg0 = serrors.New("zero-length segment[0] in peering path") - errPeeringEmptySeg1 = serrors.New("zero-length segment[1] in peering path") - errPeeringNonemptySeg2 = serrors.New("non-zero-length segment[2] in peering path") - errShortPacket = serrors.New("Packet is too short") - errBFDSessionDown = serrors.New("bfd session down") + alreadySet = errors.New("already set") + invalidSrcIA = errors.New("invalid source ISD-AS") + invalidDstIA = errors.New("invalid destination ISD-AS") + invalidSrcAddrForTransit = errors.New("invalid source address for transit pkt") + cannotRoute = errors.New("cannot route, dropping pkt") + emptyValue = errors.New("empty value") + malformedPath = errors.New("malformed path content") + modifyExisting = errors.New("modifying a running dataplane is not allowed") + noSVCBackend = errors.New("cannot find internal IP for the SVC") + unsupportedPathType = errors.New("unsupported path type") + unsupportedPathTypeNextHeader = errors.New("unsupported combination") + noBFDSessionFound = errors.New("no BFD sessions was found") + noBFDSessionConfigured = errors.New("no BFD sessions have been configured") + errBFDDisabled = errors.New("BFD is disabled") + errPeeringEmptySeg0 = errors.New("zero-length segment[0] in peering path") + errPeeringEmptySeg1 = errors.New("zero-length segment[1] in peering path") + errPeeringNonemptySeg2 = errors.New("non-zero-length segment[2] in peering path") + errShortPacket = errors.New("Packet is too short") + errBFDSessionDown = errors.New("bfd session down") + expiredHop = errors.New("expired hop") + ingressInterfaceInvalid = errors.New("ingress interface invalid") + macVerificationFailed = errors.New("MAC verification failed") + badPacketSize = errors.New("bad packet size") + slowPathRequired = errors.New("slow-path required") + // zeroBuffer will be used to reset the Authenticator option in the // scionPacketProcessor.OptAuth zeroBuffer = make([]byte, 16) @@ -152,15 +158,6 @@ type drkeyProvider interface { ) (drkey.ASHostKey, error) } -type scmpError struct { - TypeCode slayers.SCMPTypeCode - Cause error -} - -func (e scmpError) Error() string { - return serrors.New("scmp", "typecode", e.TypeCode, "cause", e.Cause).Error() -} - // SetIA sets the local IA for the dataplane. func (d *DataPlane) SetIA(ia addr.IA) error { d.mtx.Lock() @@ -511,7 +508,7 @@ func (d *DataPlane) Run(ctx context.Context, cfg *RunConfig) error { cfg.BatchSize) d.initPacketPool(cfg, processorQueueSize) - procQs, fwQs := initQueues(cfg, d.interfaces, processorQueueSize) + procQs, fwQs, slowQs := initQueues(cfg, d.interfaces, processorQueueSize) for ifID, conn := range d.interfaces { go func(ifID uint16, conn BatchConn) { @@ -526,7 +523,13 @@ func (d *DataPlane) Run(ctx context.Context, cfg *RunConfig) error { for i := 0; i < cfg.NumProcessors; i++ { go func(i int) { defer log.HandlePanic() - d.runProcessor(i, procQs[i], fwQs) + d.runProcessor(i, procQs[i], fwQs, slowQs[i%cfg.NumSlowPathProcessors]) + }(i) + } + for i := 0; i < cfg.NumSlowPathProcessors; i++ { + go func(i int) { + defer log.HandlePanic() + d.runSlowPathProcessor(i, slowQs[i], fwQs) }(i) } @@ -548,7 +551,7 @@ func (d *DataPlane) Run(ctx context.Context, cfg *RunConfig) error { // current dataplane settings and allocates all the buffers func (d *DataPlane) initPacketPool(cfg *RunConfig, processorQueueSize int) { poolSize := len(d.interfaces)*cfg.BatchSize + - cfg.NumProcessors*(processorQueueSize+1) + + (cfg.NumProcessors+cfg.NumSlowPathProcessors)*(processorQueueSize+1) + len(d.interfaces)*(2*cfg.BatchSize) log.Debug("Initialize packet pool of size", "poolSize", poolSize) @@ -560,17 +563,22 @@ func (d *DataPlane) initPacketPool(cfg *RunConfig, processorQueueSize int) { // initializes the processing routines and forwarders queues func initQueues(cfg *RunConfig, interfaces map[uint16]BatchConn, - processorQueueSize int) ([]chan packet, map[uint16]chan packet) { + processorQueueSize int) ([]chan packet, map[uint16]chan packet, + []chan slowPacket) { procQs := make([]chan packet, cfg.NumProcessors) for i := 0; i < cfg.NumProcessors; i++ { procQs[i] = make(chan packet, processorQueueSize) } + slowQs := make([]chan slowPacket, cfg.NumSlowPathProcessors) + for i := 0; i < cfg.NumSlowPathProcessors; i++ { + slowQs[i] = make(chan slowPacket, processorQueueSize) + } fwQs := make(map[uint16]chan packet) for ifID := range interfaces { fwQs[ifID] = make(chan packet, cfg.BatchSize) } - return procQs, fwQs + return procQs, fwQs, slowQs } type packet struct { @@ -585,6 +593,11 @@ type packet struct { rawPacket []byte } +type slowPacket struct { + packet + slowPathRequest slowPathRequest +} + func (d *DataPlane) runReceiver(ifID uint16, conn BatchConn, cfg *RunConfig, procQs []chan packet) { @@ -675,11 +688,10 @@ func (d *DataPlane) returnPacketToPool(pkt []byte) { } func (d *DataPlane) runProcessor(id int, q <-chan packet, - fwQs map[uint16]chan packet) { + fwQs map[uint16]chan packet, slowQ chan<- slowPacket) { log.Debug("Initialize processor with", "id", id) processor := newPacketProcessor(d) - var scmpErr scmpError for d.running { p, ok := <-q if !ok { @@ -691,10 +703,14 @@ func (d *DataPlane) runProcessor(id int, q <-chan packet, egress := result.EgressID switch { case err == nil: - case errors.As(err, &scmpErr): - if !scmpErr.TypeCode.InfoMsg() { - log.Debug("SCMP", "err", scmpErr) + case errors.Is(err, slowPathRequired): + select { + case slowQ <- slowPacket{p, result.SlowPathRequest}: + default: + metrics.DroppedPacketsBusySlowPath.Inc() + d.returnPacketToPool(p.rawPacket) } + continue default: log.Debug("Error processing packet", "err", err) metrics.DroppedPacketsInvalid.Inc() @@ -725,6 +741,150 @@ func (d *DataPlane) runProcessor(id int, q <-chan packet, } } +func (d *DataPlane) runSlowPathProcessor(id int, q <-chan slowPacket, + fwQs map[uint16]chan packet) { + + log.Debug("Initialize slow-path processor with", "id", id) + processor := newSlowPathProcessor(d) + for d.running { + p, ok := <-q + if !ok { + continue + } + metrics := d.forwardingMetrics[p.packet.ingress] + res, err := processor.processPacket(p) + if err != nil { + log.Debug("Error processing packet", "err", err) + metrics.DroppedPacketsInvalid.Inc() + d.returnPacketToPool(p.packet.rawPacket) + continue + } + p.packet.dstAddr = res.OutAddr + p.packet.rawPacket = res.OutPkt + + fwCh, ok := fwQs[res.EgressID] + if !ok { + log.Debug("Error determining forwarder. Egress is invalid", "egress", res.EgressID) + d.returnPacketToPool(p.packet.rawPacket) + continue + } + select { + case fwCh <- p.packet: + default: + d.returnPacketToPool(p.packet.rawPacket) + } + } +} + +func newSlowPathProcessor(d *DataPlane) *slowPathPacketProcessor { + p := &slowPathPacketProcessor{ + d: d, + buffer: gopacket.NewSerializeBuffer(), + macInputBuffer: make([]byte, spao.MACBufferSize), + drkeyProvider: &drkeyutil.FakeProvider{ + EpochDuration: drkeyutil.LoadEpochDuration(), + AcceptanceWindow: drkeyutil.LoadAcceptanceWindow(), + }, + optAuth: slayers.PacketAuthOption{EndToEndOption: new(slayers.EndToEndOption)}, + validAuthBuf: make([]byte, 16), + } + p.scionLayer.RecyclePaths() + return p +} + +type slowPathPacketProcessor struct { + d *DataPlane + ingressID uint16 + rawPkt []byte + srcAddr *net.UDPAddr + buffer gopacket.SerializeBuffer + + scionLayer slayers.SCION + hbhLayer slayers.HopByHopExtnSkipper + e2eLayer slayers.EndToEndExtnSkipper + lastLayer gopacket.DecodingLayer + path *scion.Raw + + // macInputBuffer avoid allocating memory during processing. + macInputBuffer []byte + + // optAuth is a reusable Packet Authenticator Option + optAuth slayers.PacketAuthOption + // validAuthBuf is a reusable buffer for the authentication tag + // to be used in the hasValidAuth() method. + validAuthBuf []byte + + // DRKey key derivation for SCMP authentication + drkeyProvider drkeyProvider +} + +func (p *slowPathPacketProcessor) reset() { + if err := p.buffer.Clear(); err != nil { + log.Debug("Error while clearing buffer", "err", err) + } + p.path = nil + p.hbhLayer = slayers.HopByHopExtnSkipper{} + p.e2eLayer = slayers.EndToEndExtnSkipper{} +} + +func (p *slowPathPacketProcessor) processPacket(pkt slowPacket) (processResult, error) { + var err error + p.reset() + p.ingressID = pkt.ingress + p.srcAddr = pkt.srcAddr + p.rawPkt = pkt.rawPacket + + p.lastLayer, err = decodeLayers(pkt.rawPacket, &p.scionLayer, &p.hbhLayer, &p.e2eLayer) + if err != nil { + return processResult{}, err + } + pathType := p.scionLayer.PathType + switch pathType { + case scion.PathType: + var ok bool + p.path, ok = p.scionLayer.Path.(*scion.Raw) + if !ok { + return processResult{}, malformedPath + } + case epic.PathType: + epicPath, ok := p.scionLayer.Path.(*epic.Path) + if !ok { + return processResult{}, malformedPath + } + p.path = epicPath.ScionPath + if p.path == nil { + return processResult{}, malformedPath + } + default: + //unsupported path type + return processResult{}, serrors.New("Path type not supported for slow-path", + "type", pathType) + } + switch pkt.slowPathRequest.typ { + case slowPathSCMP: //SCMP + s := pkt.slowPathRequest + var layer gopacket.SerializableLayer + switch s.scmpType { + case slayers.SCMPTypeParameterProblem: + layer = &slayers.SCMPParameterProblem{Pointer: s.pointer} + case slayers.SCMPTypeDestinationUnreachable: + layer = &slayers.SCMPDestinationUnreachable{} + case slayers.SCMPTypeExternalInterfaceDown: + layer = &slayers.SCMPExternalInterfaceDown{IA: s.ia, + IfID: uint64(s.interfaceId)} + case slayers.SCMPTypeInternalConnectivityDown: + layer = &slayers.SCMPInternalConnectivityDown{IA: s.ia, + Ingress: uint64(s.ingressId), Egress: uint64(s.egressId)} + } + return p.packSCMP(s.scmpType, s.code, layer, s.cause) + + case slowPathRouterAlert: //Traceroute + return p.handleSCMPTraceRouteRequest(pkt.slowPathRequest.interfaceId) + default: + panic("Unsupported slow-path type") + } +} + func (d *DataPlane) runForwarder(ifID uint16, conn BatchConn, cfg *RunConfig, c <-chan packet) { @@ -818,29 +978,18 @@ func (d *DataPlane) initMetrics() { } type processResult struct { - EgressID uint16 - OutAddr *net.UDPAddr - OutPkt []byte + EgressID uint16 + OutAddr *net.UDPAddr + OutPkt []byte + SlowPathRequest slowPathRequest } func newPacketProcessor(d *DataPlane) *scionPacketProcessor { p := &scionPacketProcessor{ - d: d, - buffer: gopacket.NewSerializeBuffer(), - mac: d.macFactory(), - macBuffers: macBuffers{ - scionInput: make([]byte, path.MACBufferSize), - epicInput: make([]byte, libepic.MACBufferSize), - drkeyInput: make([]byte, spao.MACBufferSize), - }, - // TODO(JordiSubira): Replace this with a useful implementation. - - drkeyProvider: &drkeyutil.FakeProvider{ - EpochDuration: drkeyutil.LoadEpochDuration(), - AcceptanceWindow: drkeyutil.LoadAcceptanceWindow(), - }, - optAuth: slayers.PacketAuthOption{EndToEndOption: new(slayers.EndToEndOption)}, - validAuthBuf: make([]byte, 16), + d: d, + buffer: gopacket.NewSerializeBuffer(), + mac: d.macFactory(), + macInputBuffer: make([]byte, max(path.MACBufferSize, libepic.MACBufferSize)), } p.scionLayer.RecyclePaths() return p @@ -1005,7 +1154,7 @@ func (p *scionPacketProcessor) processEPIC() (processResult, error) { HVF = epicPath.LHVF } err = libepic.VerifyHVF(p.cachedMac, epicPath.PktID, - &p.scionLayer, firstInfo.Timestamp, HVF, p.macBuffers.epicInput) + &p.scionLayer, firstInfo.Timestamp, HVF, p.macInputBuffer[:libepic.MACBufferSize]) if err != nil { // TODO(mawyss): Send back SCMP packet return processResult{}, err @@ -1054,29 +1203,37 @@ type scionPacketProcessor struct { // cachedMac contains the full 16 bytes of the MAC. Will be set during processing. // For a hop performing an Xover, it is the MAC corresponding to the down segment. cachedMac []byte - // macBuffers avoid allocating memory during processing. - macBuffers macBuffers + // macInputBuffer avoid allocating memory during processing. + macInputBuffer []byte // bfdLayer is reusable buffer for parsing BFD messages bfdLayer layers.BFD - // optAuth is a reusable Packet Authenticator Option - optAuth slayers.PacketAuthOption - // validAuthBuf is a reusable buffer for the authentication tag - // to be used in the hasValidAuth() method. - validAuthBuf []byte - - // DRKey key derivation for SCMP authentication - drkeyProvider drkeyProvider } -// macBuffers are preallocated buffers for the in- and outputs of MAC functions. -type macBuffers struct { - scionInput []byte - epicInput []byte - drkeyInput []byte +type slowPathType int + +const ( + slowPathSCMP slowPathType = iota + slowPathRouterAlert +) + +type slowPathRequest struct { + typ slowPathType + scmpType slayers.SCMPType + code slayers.SCMPCode + cause error + + // The parameters. Only those used for that particular mode and + // type will be valid. + + pointer uint16 + ia addr.IA + interfaceId uint16 + ingressId uint16 + egressId uint16 } -func (p *scionPacketProcessor) packSCMP( +func (p *slowPathPacketProcessor) packSCMP( typ slayers.SCMPType, code slayers.SCMPCode, scmpP gopacket.SerializableLayer, @@ -1119,30 +1276,35 @@ func (p *scionPacketProcessor) parsePath() (processResult, error) { return processResult{}, nil } -func (p *scionPacketProcessor) determinePeer() (processResult, error) { - if !p.infoField.Peer { - return processResult{}, nil +func determinePeer(pathMeta scion.MetaHdr, inf path.InfoField) (bool, error) { + if !inf.Peer { + return false, nil } - if p.path.PathMeta.SegLen[0] == 0 { - return processResult{}, errPeeringEmptySeg0 + if pathMeta.SegLen[0] == 0 { + return false, errPeeringEmptySeg0 } - if p.path.PathMeta.SegLen[1] == 0 { - return processResult{}, errPeeringEmptySeg1 + if pathMeta.SegLen[1] == 0 { + return false, errPeeringEmptySeg1 } - if p.path.PathMeta.SegLen[2] != 0 { - return processResult{}, errPeeringNonemptySeg2 + if pathMeta.SegLen[2] != 0 { + return false, errPeeringNonemptySeg2 } // The peer hop fields are the last hop field on the first path // segment (at SegLen[0] - 1) and the first hop field of the second // path segment (at SegLen[0]). The below check applies only // because we already know this is a well-formed peering path. - currHF := p.path.PathMeta.CurrHF - segLen := p.path.PathMeta.SegLen[0] - p.peering = currHF == segLen-1 || currHF == segLen - return processResult{}, nil + currHF := pathMeta.CurrHF + segLen := pathMeta.SegLen[0] + return currHF == segLen-1 || currHF == segLen, nil +} + +func (p *scionPacketProcessor) determinePeer() (processResult, error) { + peer, err := determinePeer(p.path.PathMeta, p.infoField) + p.peering = peer + return processResult{}, err } func (p *scionPacketProcessor) validateHopExpiry() (processResult, error) { @@ -1152,13 +1314,15 @@ func (p *scionPacketProcessor) validateHopExpiry() (processResult, error) { if !expired { return processResult{}, nil } - return p.packSCMP( - slayers.SCMPTypeParameterProblem, - slayers.SCMPCodePathExpired, - &slayers.SCMPParameterProblem{Pointer: p.currentHopPointer()}, - serrors.New("expired hop", "cons_dir", p.infoField.ConsDir, "if_id", p.ingressID, - "curr_inf", p.path.PathMeta.CurrINF, "curr_hf", p.path.PathMeta.CurrHF), - ) + log.Debug("SCMP: expired hop", "cons_dir", p.infoField.ConsDir, "if_id", p.ingressID, + "curr_inf", p.path.PathMeta.CurrINF, "curr_hf", p.path.PathMeta.CurrHF) + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeParameterProblem, + code: slayers.SCMPCodePathExpired, + pointer: p.currentHopPointer(), + cause: expiredHop, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } func (p *scionPacketProcessor) validateIngressID() (processResult, error) { @@ -1169,13 +1333,15 @@ func (p *scionPacketProcessor) validateIngressID() (processResult, error) { errCode = slayers.SCMPCodeUnknownHopFieldEgress } if p.ingressID != 0 && p.ingressID != pktIngressID { - return p.packSCMP( - slayers.SCMPTypeParameterProblem, - errCode, - &slayers.SCMPParameterProblem{Pointer: p.currentHopPointer()}, - serrors.New("ingress interface invalid", - "pkt_ingress", pktIngressID, "router_ingress", p.ingressID), - ) + log.Debug("SCMP: ingress interface invalid", "pkt_ingress", + pktIngressID, "router_ingress", p.ingressID) + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeParameterProblem, + code: errCode, + pointer: p.currentHopPointer(), + cause: ingressInterfaceInvalid, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } return processResult{}, nil } @@ -1208,22 +1374,26 @@ func (p *scionPacketProcessor) validateSrcDstIA() (processResult, error) { // invalidSrcIA is a helper to return an SCMP error for an invalid SrcIA. func (p *scionPacketProcessor) invalidSrcIA() (processResult, error) { - return p.packSCMP( - slayers.SCMPTypeParameterProblem, - slayers.SCMPCodeInvalidSourceAddress, - &slayers.SCMPParameterProblem{Pointer: uint16(slayers.CmnHdrLen + addr.IABytes)}, - invalidSrcIA, - ) + log.Debug("SCMP: invalid source IA") + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeParameterProblem, + code: slayers.SCMPCodeInvalidSourceAddress, + pointer: uint16(slayers.CmnHdrLen + addr.IABytes), + cause: invalidSrcIA, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } // invalidDstIA is a helper to return an SCMP error for an invalid DstIA. func (p *scionPacketProcessor) invalidDstIA() (processResult, error) { - return p.packSCMP( - slayers.SCMPTypeParameterProblem, - slayers.SCMPCodeInvalidDestinationAddress, - &slayers.SCMPParameterProblem{Pointer: uint16(slayers.CmnHdrLen)}, - invalidDstIA, - ) + log.Debug("SCMP: invalid destination IA") + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeParameterProblem, + code: slayers.SCMPCodeInvalidDestinationAddress, + pointer: uint16(slayers.CmnHdrLen), + cause: invalidDstIA, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } // validateTransitUnderlaySrc checks that the source address of transit packets @@ -1254,12 +1424,14 @@ func (p *scionPacketProcessor) validateEgressID() (processResult, error) { if !p.infoField.ConsDir { errCode = slayers.SCMPCodeUnknownHopFieldIngress } - return p.packSCMP( - slayers.SCMPTypeParameterProblem, - errCode, - &slayers.SCMPParameterProblem{Pointer: p.currentHopPointer()}, - cannotRoute, - ) + log.Debug("SCMP: cannot route") + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeParameterProblem, + code: errCode, + pointer: p.currentHopPointer(), + cause: cannotRoute, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } ingress, egress := p.d.linkTypes[p.ingressID], p.d.linkTypes[pktEgressID] @@ -1282,12 +1454,15 @@ func (p *scionPacketProcessor) validateEgressID() (processResult, error) { case ingress == topology.Peer && egress == topology.Child: return processResult{}, nil default: // malicious - return p.packSCMP( - slayers.SCMPTypeParameterProblem, - slayers.SCMPCodeInvalidPath, // XXX(matzf) new code InvalidHop? - &slayers.SCMPParameterProblem{Pointer: p.currentHopPointer()}, - serrors.WithCtx(cannotRoute, "ingress_id", p.ingressID, "ingress_type", ingress, - "egress_id", pktEgressID, "egress_type", egress)) + log.Debug("SCMP: cannot route", "ingress_id", p.ingressID, + "ingress_type", ingress, "egress_id", pktEgressID, "egress_type", egress) + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeParameterProblem, + code: slayers.SCMPCodeInvalidPath, // XXX(matzf) new code InvalidHop?, + pointer: p.currentHopPointer(), + cause: cannotRoute, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } } // Check that the interface pair is valid on a segment switch. @@ -1303,12 +1478,15 @@ func (p *scionPacketProcessor) validateEgressID() (processResult, error) { case ingress == topology.Child && egress == topology.Child: return processResult{}, nil default: - return p.packSCMP( - slayers.SCMPTypeParameterProblem, - slayers.SCMPCodeInvalidSegmentChange, - &slayers.SCMPParameterProblem{Pointer: p.currentInfoPointer()}, - serrors.WithCtx(cannotRoute, "ingress_id", p.ingressID, "ingress_type", ingress, - "egress_id", pktEgressID, "egress_type", egress)) + log.Debug("SCMP: cannot route", "ingress_id", p.ingressID, "ingress_type", ingress, + "egress_id", pktEgressID, "egress_type", egress) + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeParameterProblem, + code: slayers.SCMPCodeInvalidSegmentChange, + pointer: p.currentInfoPointer(), + cause: cannotRoute, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } } @@ -1336,21 +1514,21 @@ func (p *scionPacketProcessor) currentHopPointer() uint16 { } func (p *scionPacketProcessor) verifyCurrentMAC() (processResult, error) { - fullMac := path.FullMAC(p.mac, p.infoField, p.hopField, p.macBuffers.scionInput) + fullMac := path.FullMAC(p.mac, p.infoField, p.hopField, p.macInputBuffer[:path.MACBufferSize]) if subtle.ConstantTimeCompare(p.hopField.Mac[:path.MacLen], fullMac[:path.MacLen]) == 0 { - return p.packSCMP( - slayers.SCMPTypeParameterProblem, - slayers.SCMPCodeInvalidHopFieldMAC, - &slayers.SCMPParameterProblem{Pointer: p.currentHopPointer()}, - serrors.New("MAC verification failed", - "expected", fmt.Sprintf("%x", fullMac[:path.MacLen]), - "actual", fmt.Sprintf("%x", p.hopField.Mac[:path.MacLen]), - "cons_dir", p.infoField.ConsDir, - "if_id", p.ingressID, - "curr_inf", p.path.PathMeta.CurrINF, - "curr_hf", p.path.PathMeta.CurrHF, - "seg_id", p.infoField.SegID), - ) + log.Debug("SCMP: MAC verification failed", "expected", fmt.Sprintf( + "%x", fullMac[:path.MacLen]), + "actual", fmt.Sprintf("%x", p.hopField.Mac[:path.MacLen]), + "cons_dir", p.infoField.ConsDir, + "if_id", p.ingressID, "curr_inf", p.path.PathMeta.CurrINF, + "curr_hf", p.path.PathMeta.CurrHF, "seg_id", p.infoField.SegID) + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeParameterProblem, + code: slayers.SCMPCodeInvalidHopFieldMAC, + pointer: p.currentHopPointer(), + cause: macVerificationFailed, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } // Add the full MAC to the SCION packet processor, // such that EPIC does not need to recalculate it. @@ -1363,11 +1541,13 @@ func (p *scionPacketProcessor) resolveInbound() (*net.UDPAddr, processResult, er a, err := p.d.resolveLocalDst(p.scionLayer) switch { case errors.Is(err, noSVCBackend): - r, err := p.packSCMP( - slayers.SCMPTypeDestinationUnreachable, - slayers.SCMPCodeNoRoute, - &slayers.SCMPDestinationUnreachable{}, err) - return nil, r, err + log.Debug("SCMP: no SVC backend") + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeDestinationUnreachable, + code: slayers.SCMPCodeNoRoute, + cause: err, + } + return nil, processResult{SlowPathRequest: slowPathRequest}, slowPathRequired default: return a, processResult{}, nil } @@ -1442,20 +1622,28 @@ func (p *scionPacketProcessor) validateEgressUp() (processResult, error) { egressID := p.egressInterface() if v, ok := p.d.bfdSessions[egressID]; ok { if !v.IsUp() { - typ := slayers.SCMPTypeExternalInterfaceDown - var scmpP gopacket.SerializableLayer = &slayers.SCMPExternalInterfaceDown{ - IA: p.d.localIA, - IfID: uint64(egressID), - } + var s slowPathRequest + log.Debug("SCMP: bfd session down") if _, external := p.d.external[egressID]; !external { - typ = slayers.SCMPTypeInternalConnectivityDown - scmpP = &slayers.SCMPInternalConnectivityDown{ - IA: p.d.localIA, - Ingress: uint64(p.ingressID), - Egress: uint64(egressID), + s = slowPathRequest{ + scmpType: slayers.SCMPTypeInternalConnectivityDown, + code: 0, + ia: p.d.localIA, + ingressId: p.ingressID, + egressId: egressID, + cause: errBFDSessionDown, + } + } else { + s = slowPathRequest{ + scmpType: slayers.SCMPTypeExternalInterfaceDown, + code: 0, + ia: p.d.localIA, + interfaceId: egressID, + cause: errBFDSessionDown, } } - return p.packSCMP(typ, 0, scmpP, errBFDSessionDown) + return processResult{SlowPathRequest: s}, slowPathRequired + } } return processResult{}, nil @@ -1473,7 +1661,11 @@ func (p *scionPacketProcessor) handleIngressRouterAlert() (processResult, error) if err := p.path.SetHopField(p.hopField, int(p.path.PathMeta.CurrHF)); err != nil { return processResult{}, serrors.WrapStr("update hop field", err) } - return p.handleSCMPTraceRouteRequest(p.ingressID) + slowPathRequest := slowPathRequest{ + typ: slowPathRouterAlert, + interfaceId: p.ingressID, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } func (p *scionPacketProcessor) ingressRouterAlertFlag() *bool { @@ -1496,7 +1688,11 @@ func (p *scionPacketProcessor) handleEgressRouterAlert() (processResult, error) if err := p.path.SetHopField(p.hopField, int(p.path.PathMeta.CurrHF)); err != nil { return processResult{}, serrors.WrapStr("update hop field", err) } - return p.handleSCMPTraceRouteRequest(egressID) + slowPathRequest := slowPathRequest{ + typ: slowPathRouterAlert, + interfaceId: egressID, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } func (p *scionPacketProcessor) egressRouterAlertFlag() *bool { @@ -1506,7 +1702,7 @@ func (p *scionPacketProcessor) egressRouterAlertFlag() *bool { return &p.hopField.EgressRouterAlert } -func (p *scionPacketProcessor) handleSCMPTraceRouteRequest( +func (p *slowPathPacketProcessor) handleSCMPTraceRouteRequest( interfaceID uint16) (processResult, error) { if p.lastLayer.NextLayerType() != slayers.LayerTypeSCMP { @@ -1542,13 +1738,15 @@ func (p *scionPacketProcessor) validatePktLen() (processResult, error) { if int(p.scionLayer.PayloadLen) == len(p.scionLayer.Payload) { return processResult{}, nil } - return p.packSCMP( - slayers.SCMPTypeParameterProblem, - slayers.SCMPCodeInvalidPacketSize, - &slayers.SCMPParameterProblem{Pointer: 0}, - serrors.New("bad packet size", - "header", p.scionLayer.PayloadLen, "actual", len(p.scionLayer.Payload)), - ) + log.Debug("SCMP: bad packet size", "header", p.scionLayer.PayloadLen, + "actual", len(p.scionLayer.Payload)) + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeParameterProblem, + code: slayers.SCMPCodeInvalidPacketSize, + pointer: 0, + cause: badPacketSize, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } func (p *scionPacketProcessor) process() (processResult, error) { @@ -1636,12 +1834,14 @@ func (p *scionPacketProcessor) process() (processResult, error) { if !p.infoField.ConsDir { errCode = slayers.SCMPCodeUnknownHopFieldIngress } - return p.packSCMP( - slayers.SCMPTypeParameterProblem, - errCode, - &slayers.SCMPParameterProblem{Pointer: p.currentHopPointer()}, - cannotRoute, - ) + log.Debug("SCMP: cannot route") + slowPathRequest := slowPathRequest{ + scmpType: slayers.SCMPTypeParameterProblem, + code: errCode, + pointer: p.currentHopPointer(), + cause: cannotRoute, + } + return processResult{SlowPathRequest: slowPathRequest}, slowPathRequired } func (p *scionPacketProcessor) processOHP() (processResult, error) { @@ -1677,7 +1877,7 @@ func (p *scionPacketProcessor) processOHP() (processResult, error) { "type", "ohp", "egress", ohp.FirstHop.ConsEgress, "neighborIA", neighborIA, "dstIA", s.DstIA) } - mac := path.MAC(p.mac, ohp.Info, ohp.FirstHop, p.macBuffers.scionInput) + mac := path.MAC(p.mac, ohp.Info, ohp.FirstHop, p.macInputBuffer[:path.MACBufferSize]) if subtle.ConstantTimeCompare(ohp.FirstHop.Mac[:], mac[:]) == 0 { // TODO parameter problem -> invalid MAC return processResult{}, serrors.New("MAC", "expected", fmt.Sprintf("%x", mac), @@ -1712,7 +1912,8 @@ func (p *scionPacketProcessor) processOHP() (processResult, error) { // XXX(roosd): Here we leak the buffer into the SCION packet header. // This is okay because we do not operate on the buffer or the packet // for the rest of processing. - ohp.SecondHop.Mac = path.MAC(p.mac, ohp.Info, ohp.SecondHop, p.macBuffers.scionInput) + ohp.SecondHop.Mac = path.MAC(p.mac, ohp.Info, ohp.SecondHop, + p.macInputBuffer[:path.MACBufferSize]) if err := updateSCIONLayer(p.rawPkt, s, p.buffer); err != nil { return processResult{}, err @@ -1861,7 +2062,7 @@ func (b *bfdSend) Send(bfd *layers.BFD) error { return err } -func (p *scionPacketProcessor) prepareSCMP( +func (p *slowPathPacketProcessor) prepareSCMP( typ slayers.SCMPType, code slayers.SCMPCode, scmpP gopacket.SerializableLayer, @@ -1901,8 +2102,13 @@ func (p *scionPacketProcessor) prepareSCMP( } revPath := revPathTmp.(*scion.Decoded) + peering, err := determinePeer(revPath.PathMeta, revPath.InfoFields[revPath.PathMeta.CurrINF]) + if err != nil { + return nil, serrors.Wrap(cannotRoute, err, "details", "peering cannot be determined") + } + // Revert potential path segment switches that were done during processing. - if revPath.IsXover() && !p.peering { + if revPath.IsXover() && !peering { // An effective cross-over is a change of segment other than at // a peering hop. if err := revPath.IncPath(); err != nil { @@ -1914,7 +2120,7 @@ func (p *scionPacketProcessor) prepareSCMP( _, external := p.d.external[p.ingressID] if external { infoField := &revPath.InfoFields[revPath.PathMeta.CurrINF] - if infoField.ConsDir && !p.peering { + if infoField.ConsDir && !peering { hopField := revPath.HopFields[revPath.PathMeta.CurrHF] infoField.UpdateSegID(hopField.Mac) } @@ -2017,7 +2223,7 @@ func (p *scionPacketProcessor) prepareSCMP( PldType: slayers.L4SCMP, Pld: p.buffer.Bytes(), }, - p.macBuffers.drkeyInput, + p.macInputBuffer, p.optAuth.Authenticator(), ) if err != nil { @@ -2033,10 +2239,11 @@ func (p *scionPacketProcessor) prepareSCMP( return nil, serrors.Wrap(cannotRoute, err, "details", "serializing SCION header") } - return p.buffer.Bytes(), scmpError{TypeCode: scmpH.TypeCode, Cause: cause} + log.Debug("scmp", "typecode", scmpH.TypeCode, "cause", cause) + return p.buffer.Bytes(), nil } -func (p *scionPacketProcessor) resetSPAOMetadata(key drkey.ASHostKey, now time.Time) error { +func (p *slowPathPacketProcessor) resetSPAOMetadata(key drkey.ASHostKey, now time.Time) error { // For creating SCMP responses we use sender side. dir := slayers.PacketAuthSenderSide drkeyType := slayers.PacketAuthASHost @@ -2059,7 +2266,7 @@ func (p *scionPacketProcessor) resetSPAOMetadata(key drkey.ASHostKey, now time.T }) } -func (p *scionPacketProcessor) hasValidAuth(t time.Time) bool { +func (p *slowPathPacketProcessor) hasValidAuth(t time.Time) bool { // Check if e2eLayer was parsed for this packet if !p.lastLayer.CanDecode().Contains(slayers.LayerTypeEndToEndExtn) { return false @@ -2107,13 +2314,12 @@ func (p *scionPacketProcessor) hasValidAuth(t time.Time) bool { PldType: slayers.L4SCMP, Pld: p.lastLayer.LayerPayload(), }, - p.macBuffers.drkeyInput, + p.macInputBuffer, p.validAuthBuf, ) if err != nil { return false } - // compare incoming authField with computed authentication tag return subtle.ConstantTimeCompare(authOption.Authenticator(), p.validAuthBuf) != 0 } @@ -2164,6 +2370,7 @@ type forwardingMetrics struct { DroppedPacketsInvalid prometheus.Counter DroppedPacketsBusyProcessor prometheus.Counter DroppedPacketsBusyForwarder prometheus.Counter + DroppedPacketsBusySlowPath prometheus.Counter ProcessedPackets prometheus.Counter } @@ -2181,6 +2388,8 @@ func initForwardingMetrics(metrics *Metrics, labels prometheus.Labels) forwardin c.DroppedPacketsBusyProcessor = metrics.DroppedPacketsTotal.With(labels) labels["reason"] = "busy_forwarder" c.DroppedPacketsBusyForwarder = metrics.DroppedPacketsTotal.With(labels) + labels["reason"] = "busy_slow_path" + c.DroppedPacketsBusySlowPath = metrics.DroppedPacketsTotal.With(labels) c.InputBytesTotal.Add(0) c.InputPacketsTotal.Add(0) @@ -2189,6 +2398,7 @@ func initForwardingMetrics(metrics *Metrics, labels prometheus.Labels) forwardin c.DroppedPacketsInvalid.Add(0) c.DroppedPacketsBusyProcessor.Add(0) c.DroppedPacketsBusyForwarder.Add(0) + c.DroppedPacketsBusySlowPath.Add(0) c.ProcessedPackets.Add(0) return c } diff --git a/router/dataplane_internal_test.go b/router/dataplane_internal_test.go index 60291aaa4..6e92a8219 100644 --- a/router/dataplane_internal_test.go +++ b/router/dataplane_internal_test.go @@ -34,6 +34,7 @@ import ( "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" + "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/pkg/slayers/path/scion" @@ -41,6 +42,8 @@ import ( "github.com/scionproto/scion/router/mock_router" ) +var testKey = []byte("testkey_xxxxxxxx") + // TestReceiver sets up a mocked batchConn, starts the receiver that reads from // this batchConn and forwards it to the processing routines channels. We verify // by directly reading from the processing routine channels that we received @@ -80,7 +83,7 @@ func TestReceiver(t *testing.T) { BatchSize: 64, } dp.initPacketPool(runConfig, 64) - procCh, _ := initQueues(runConfig, dp.interfaces, 64) + procCh, _, _ := initQueues(runConfig, dp.interfaces, 64) initialPoolSize := len(dp.packetPool) dp.running = true dp.initMetrics() @@ -174,7 +177,7 @@ func TestForwarder(t *testing.T) { BatchSize: 64, } dp.initPacketPool(runConfig, 64) - _, fwCh := initQueues(runConfig, dp.interfaces, 64) + _, fwCh, _ := initQueues(runConfig, dp.interfaces, 64) initialPoolSize := len(dp.packetPool) dp.running = true dp.initMetrics() @@ -414,6 +417,140 @@ func TestComputeProcIdErrorCases(t *testing.T) { } } +func TestSlowPathProcessing(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + payload := []byte("actualpayloadbytes") + testCases := map[string]struct { + mockMsg func() []byte + prepareDP func(*gomock.Controller) *DataPlane + expectedSlowPathRequest slowPathRequest + srcInterface uint16 + expectedLayerType gopacket.LayerType + }{ + "svc nobackend": { + prepareDP: func(ctrl *gomock.Controller) *DataPlane { + return NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, + map[addr.SVC][]*net.UDPAddr{}, + xtest.MustParseIA("1-ff00:0:110"), nil, testKey) + }, + mockMsg: func() []byte { + spkt := prepBaseMsg(t, payload, 0) + _ = spkt.SetDstAddr(addr.MustParseHost("CS")) + spkt.DstIA = xtest.MustParseIA("1-ff00:0:110") + ret := toMsg(t, spkt) + return ret + }, + srcInterface: 1, + expectedSlowPathRequest: slowPathRequest{ + typ: slowPathSCMP, + scmpType: slayers.SCMPTypeDestinationUnreachable, + code: slayers.SCMPCodeNoRoute, + cause: noSVCBackend, + }, + expectedLayerType: slayers.LayerTypeSCMPDestinationUnreachable, + }, + "svc invalid": { + prepareDP: func(ctrl *gomock.Controller) *DataPlane { + return NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, + map[addr.SVC][]*net.UDPAddr{}, + xtest.MustParseIA("1-ff00:0:110"), nil, testKey) + }, + mockMsg: func() []byte { + spkt := prepBaseMsg(t, payload, 0) + _ = spkt.SetDstAddr(addr.MustParseHost("CS")) + spkt.DstIA = xtest.MustParseIA("1-ff00:0:110") + ret := toMsg(t, spkt) + return ret + }, + srcInterface: 1, + expectedSlowPathRequest: slowPathRequest{ + typ: slowPathSCMP, + scmpType: slayers.SCMPTypeDestinationUnreachable, + code: slayers.SCMPCodeNoRoute, + cause: noSVCBackend, + }, + expectedLayerType: slayers.LayerTypeSCMPDestinationUnreachable, + }, + "invalid dest": { + prepareDP: func(ctrl *gomock.Controller) *DataPlane { + return NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, + map[addr.SVC][]*net.UDPAddr{}, + xtest.MustParseIA("1-ff00:0:110"), nil, testKey) + }, + mockMsg: func() []byte { + spkt := prepBaseMsg(t, payload, 0) + spkt.DstIA = xtest.MustParseIA("1-ff00:0:f1") + ret := toMsg(t, spkt) + return ret + }, + srcInterface: 1, + expectedSlowPathRequest: slowPathRequest{ + typ: slowPathSCMP, + scmpType: slayers.SCMPTypeParameterProblem, + code: slayers.SCMPCodeInvalidDestinationAddress, + cause: invalidDstIA, + pointer: 0xc, + }, + expectedLayerType: slayers.LayerTypeSCMPParameterProblem, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + t.Parallel() + dp := tc.prepareDP(ctrl) + rawPacket := tc.mockMsg() + var srcAddr *net.UDPAddr + + processor := newPacketProcessor(dp) + result, err := processor.processPkt(rawPacket, srcAddr, tc.srcInterface) + assert.ErrorIs(t, err, SlowPathRequired) + + assert.Equal(t, tc.expectedSlowPathRequest, result.SlowPathRequest) + slowPathProcessor := newSlowPathProcessor(dp) + result, err = slowPathProcessor.processPacket(slowPacket{ + packet: packet{ + srcAddr: srcAddr, + dstAddr: result.OutAddr, + ingress: tc.srcInterface, + rawPacket: rawPacket, + }, + slowPathRequest: result.SlowPathRequest, + }) + assert.NoError(t, err) + + // here we parse the result.OutPkt to verify that it contains the correct SCMP + // header and typecodes. + packet := gopacket.NewPacket(result.OutPkt, slayers.LayerTypeSCION, gopacket.Default) + scmp := packet.Layer(slayers.LayerTypeSCMP).(*slayers.SCMP) + expectedTypeCode := slayers.CreateSCMPTypeCode(tc.expectedSlowPathRequest.scmpType, + tc.expectedSlowPathRequest.code) + assert.Equal(t, expectedTypeCode, scmp.TypeCode) + assert.NotNil(t, packet.Layer(tc.expectedLayerType)) + }) + } +} + +func toMsg(t *testing.T, spkt *slayers.SCION) []byte { + t.Helper() + buffer := gopacket.NewSerializeBuffer() + payload := []byte("actualpayloadbytes") + err := gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{FixLengths: true}, + spkt, gopacket.Payload(payload)) + require.NoError(t, err) + raw := buffer.Bytes() + ret := make([]byte, bufSize) + copy(ret, raw) + return ret[:len(raw)] +} + +func computeMAC(t *testing.T, key []byte, info path.InfoField, hf path.HopField) [path.MacLen]byte { + mac, err := scrypto.InitMac(key) + require.NoError(t, err) + return path.MAC(mac, info, hf, nil) +} + func serializedBaseMsg(t *testing.T, payload []byte, flowId uint32) []byte { s := prepBaseMsg(t, payload, flowId) buffer := gopacket.NewSerializeBuffer() @@ -440,7 +577,7 @@ func prepBaseMsg(t *testing.T, payload []byte, flowId uint32) *slayers.SCION { dpath := &scion.Decoded{ Base: scion.Base{ PathMeta: scion.MetaHdr{ - CurrHF: 1, + CurrHF: 2, SegLen: [3]uint8{3, 0, 0}, }, NumINF: 1, @@ -456,6 +593,7 @@ func prepBaseMsg(t *testing.T, payload []byte, flowId uint32) *slayers.SCION { {ConsIngress: 1, ConsEgress: 0}, }, } + dpath.HopFields[2].Mac = computeMAC(t, testKey, dpath.InfoFields[0], dpath.HopFields[2]) spkt.Path = dpath return spkt } diff --git a/router/dataplane_test.go b/router/dataplane_test.go index c83bc2701..57f3b20dd 100644 --- a/router/dataplane_test.go +++ b/router/dataplane_test.go @@ -539,8 +539,9 @@ func TestDataPlaneRun(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() runConfig := &router.RunConfig{ - NumProcessors: 8, - BatchSize: 256, + NumProcessors: 8, + BatchSize: 256, + NumSlowPathProcessors: 1, } ch := make(chan struct{}) dp := tc.prepareDP(ctrl, ch) @@ -1146,54 +1147,6 @@ func TestProcessPkt(t *testing.T) { egressInterface: 0, assertFunc: assert.NoError, }, - "svc nobackend": { - prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - map[addr.SVC][]*net.UDPAddr{}, - xtest.MustParseIA("1-ff00:0:110"), nil, key) - }, - mockMsg: func(afterProcessing bool) *ipv4.Message { - spkt, dpath := prepBaseMsg(now) - _ = spkt.SetDstAddr(addr.MustParseHost("CS")) - spkt.DstIA = xtest.MustParseIA("1-ff00:0:110") - dpath.HopFields = []path.HopField{ - {ConsIngress: 41, ConsEgress: 40}, - {ConsIngress: 31, ConsEgress: 30}, - {ConsIngress: 1, ConsEgress: 0}, - } - dpath.Base.PathMeta.CurrHF = 2 - dpath.HopFields[2].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[2]) - ret := toMsg(t, spkt, dpath) - return ret - }, - srcInterface: 1, - egressInterface: 0, - assertFunc: assertIsSCMPError(slayers.SCMPTypeDestinationUnreachable, 0), - }, - "svc invalid": { - prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - map[addr.SVC][]*net.UDPAddr{}, - xtest.MustParseIA("1-ff00:0:110"), nil, key) - }, - mockMsg: func(afterProcessing bool) *ipv4.Message { - spkt, dpath := prepBaseMsg(now) - _ = spkt.SetDstAddr(addr.MustParseHost("CS")) - spkt.DstIA = xtest.MustParseIA("1-ff00:0:110") - dpath.HopFields = []path.HopField{ - {ConsIngress: 41, ConsEgress: 40}, - {ConsIngress: 31, ConsEgress: 30}, - {ConsIngress: 1, ConsEgress: 0}, - } - dpath.Base.PathMeta.CurrHF = 2 - dpath.HopFields[2].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[2]) - ret := toMsg(t, spkt, dpath) - return ret - }, - srcInterface: 1, - egressInterface: 0, - assertFunc: assertIsSCMPError(slayers.SCMPTypeDestinationUnreachable, 0), - }, "onehop inbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP( @@ -1401,32 +1354,6 @@ func TestProcessPkt(t *testing.T) { egressInterface: 2, assertFunc: assert.NoError, }, - "invalid dest": { - prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - map[addr.SVC][]*net.UDPAddr{}, - xtest.MustParseIA("1-ff00:0:110"), nil, key) - }, - mockMsg: func(afterProcessing bool) *ipv4.Message { - spkt, dpath := prepBaseMsg(now) - spkt.DstIA = xtest.MustParseIA("1-ff00:0:f1") - dpath.HopFields = []path.HopField{ - {ConsIngress: 41, ConsEgress: 40}, - {ConsIngress: 31, ConsEgress: 404}, - {ConsIngress: 1, ConsEgress: 0}, - } - dpath.Base.PathMeta.CurrHF = 2 - dpath.HopFields[1].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[1]) - ret := toMsg(t, spkt, dpath) - return ret - }, - srcInterface: 1, - egressInterface: 0, - assertFunc: assertIsSCMPError( - slayers.SCMPTypeParameterProblem, - slayers.SCMPCodeInvalidDestinationAddress, - ), - }, "epic inbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, @@ -1655,14 +1582,3 @@ func bfd() control.BFD { RequiredMinRxInterval: 25 * time.Millisecond, } } - -// assertIsSCMPError returns an ErrorAssertionFunc asserting that error is an -// scmpError with the specified type/code. -func assertIsSCMPError(typ slayers.SCMPType, code slayers.SCMPCode) assert.ErrorAssertionFunc { - return func(t assert.TestingT, err error, args ...interface{}) bool { - target := router.SCMPError{} - return assert.ErrorAs(t, err, &target, args) && - assert.Equal(t, typ, target.TypeCode.Type(), args) && - assert.Equal(t, code, target.TypeCode.Code(), args) - } -} diff --git a/router/export_test.go b/router/export_test.go index 32d2d14b8..a82d01e5a 100644 --- a/router/export_test.go +++ b/router/export_test.go @@ -37,7 +37,7 @@ type ProcessResult struct { processResult } -type SCMPError = scmpError +var SlowPathRequired error = slowPathRequired func NewDP( external map[uint16]BatchConn, From 241d6be8461aedd5be9b6783ff0b4fe4e570c04b Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 28 Sep 2023 18:13:09 +0200 Subject: [PATCH 061/255] acceptance: de-flake cert_renewal and hidden_paths (#4399) These tests have become even more flaky with the updated CI runners; it seems that this is triggered due to using the significantly quicker docker-compose v2. Use the existing await-connectivity script to determine when a test can safely start to run, instead of sleeping for arbitrary number of seconds. --- acceptance/cert_renewal/test.py | 3 ++- acceptance/common/base.py | 20 ++++++++++++++++++++ acceptance/common/topogen.bzl | 2 ++ acceptance/hidden_paths/test.py | 7 ++++--- tools/BUILD.bazel | 6 ++++++ tools/await-connectivity | 3 ++- 6 files changed, 36 insertions(+), 5 deletions(-) diff --git a/acceptance/cert_renewal/test.py b/acceptance/cert_renewal/test.py index 0b53b2883..799fa4225 100755 --- a/acceptance/cert_renewal/test.py +++ b/acceptance/cert_renewal/test.py @@ -53,6 +53,7 @@ class Test(base.TestTopogen): """ def _run(self): + self.await_connectivity() isd_ases = scion.ASList.load("%s/gen/as_list.yml" % self.artifacts).all @@ -84,7 +85,7 @@ def _run(self): logger.info("==> Restart containers") self.setup_start() - time.sleep(5) + self.await_connectivity() logger.info("==> Check connectivity") end2end.run_fg() diff --git a/acceptance/common/base.py b/acceptance/common/base.py index a40d46dab..dda57be94 100644 --- a/acceptance/common/base.py +++ b/acceptance/common/base.py @@ -213,6 +213,26 @@ def teardown(self): if re.search(r"Exit\s+[1-9]\d*", ps): raise Exception("Failed services.\n" + ps) + def await_connectivity(self, quiet_seconds=None, timeout_seconds=None): + """ + Wait for the beaconing process in a local topology to establish full connectivity, i.e. at + least one path between any two ASes. + Runs the tool/await-connectivity script. + + Returns success when full connectivity is established or an error (exception) at + timeout (default 20s). + + Remains quiet for a configurable time (default 10s). After that, + it reports the missing segments at 1s interval. + """ + cmd = self.get_executable("await-connectivity") + cmd.cwd = self.artifacts + if quiet_seconds is not None: + cmd = cmd["-q", str(quiet_seconds)] + if timeout_seconds is not None: + cmd = cmd["-t", str(timeout_seconds)] + cmd.run_fg() + def execute_tester(self, isd_as: ISD_AS, cmd: str, *args: str) -> str: """Executes a command in the designated "tester" container for the specified ISD-AS. diff --git a/acceptance/common/topogen.bzl b/acceptance/common/topogen.bzl index 675cee50a..cc18515f0 100644 --- a/acceptance/common/topogen.bzl +++ b/acceptance/common/topogen.bzl @@ -45,6 +45,7 @@ def topogen_test( common_args = [ "--executable=scion-pki:$(location //scion-pki/cmd/scion-pki)", "--executable=topogen:$(location //tools:topogen)", + "--executable=await-connectivity:$(location //tools:await_connectivity)", "--topo=$(location %s)" % topo, ] if gateway: @@ -54,6 +55,7 @@ def topogen_test( "//scion-pki/cmd/scion-pki", "//tools:topogen", "//tools:docker_ip", + "//tools:await_connectivity", topo, ] loaders = container_loaders(tester, gateway) diff --git a/acceptance/hidden_paths/test.py b/acceptance/hidden_paths/test.py index 3a9f1af7f..cf0d3ae43 100755 --- a/acceptance/hidden_paths/test.py +++ b/acceptance/hidden_paths/test.py @@ -3,7 +3,6 @@ # Copyright 2020 Anapaya Systems import http.server -import time import threading from plumbum import cmd @@ -105,9 +104,9 @@ def setup_start(self): ("0.0.0.0", self.http_server_port), http.server.SimpleHTTPRequestHandler) server_thread = threading.Thread(target=configuration_server, args=[server]) server_thread.start() + self._server = server super().setup_start() - time.sleep(4) # Give applications time to download configurations self._testers = { "2": "tester_1-ff00_0_2", @@ -121,9 +120,11 @@ def setup_start(self): "4": "1-ff00:0:4", "5": "1-ff00:0:5", } - server.shutdown() def _run(self): + self.await_connectivity() + self._server.shutdown() # by now configuration must have been downloaded everywhere + # Group 3 self._showpaths_bidirectional("2", "3", 0) self._showpaths_bidirectional("2", "5", 0) diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel index b116c1f78..2871a5b8c 100644 --- a/tools/BUILD.bazel +++ b/tools/BUILD.bazel @@ -7,6 +7,12 @@ sh_binary( visibility = ["//visibility:public"], ) +sh_binary( + name = "await_connectivity", + srcs = ["await-connectivity"], + visibility = ["//visibility:public"], +) + py_binary( name = "gomocks", srcs = ["gomocks.py"], diff --git a/tools/await-connectivity b/tools/await-connectivity index a4e2ccc56..63ee037e8 100755 --- a/tools/await-connectivity +++ b/tools/await-connectivity @@ -13,7 +13,7 @@ # # Usage: await-connectivity -q QUIET -t TIMEOUT -set -euo pipefail +set -Eeuo pipefail QUIET=10 TIMEOUT=20 @@ -83,6 +83,7 @@ main() { parse_opts "$@" # poor bash-man's yaml parser + stat gen/as_list.yml > /dev/null # ensure file exists; command substitutions below don't fail because local (!?) local cores=$(sed -n '1,/Non-core/{s/^- //p}' gen/as_list.yml) local noncores=$(sed -n '/Non-core/,${s/^- //p}' gen/as_list.yml) From df0f505e005dd468f56fc2faea4f7aa75f8ae701 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Fri, 29 Sep 2023 17:01:28 +0200 Subject: [PATCH 062/255] Create WorkItem (#4400) * Create WorkItem Just as basic as the others. Wanted some category that's neither bug nor proposal. Just work to do; feature, performance enhancement, etc. * Update WorkItem Apparently "Name" can be a phrase, so...making it nicer on the eyes. --- .github/ISSUE_TEMPLATE/WorkItem | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/WorkItem diff --git a/.github/ISSUE_TEMPLATE/WorkItem b/.github/ISSUE_TEMPLATE/WorkItem new file mode 100644 index 000000000..8ac5d4a0f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/WorkItem @@ -0,0 +1,5 @@ +--- +name: Work Item +about: "Something needs doing" +labels: workitem +--- From 95d4329909f6f76643862e0e9755beadc9a60790 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Fri, 29 Sep 2023 17:32:07 +0200 Subject: [PATCH 063/255] Rename WorkItem to 02-workitem.md (#4401) --- .github/ISSUE_TEMPLATE/{WorkItem => 02-workitem.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/ISSUE_TEMPLATE/{WorkItem => 02-workitem.md} (100%) diff --git a/.github/ISSUE_TEMPLATE/WorkItem b/.github/ISSUE_TEMPLATE/02-workitem.md similarity index 100% rename from .github/ISSUE_TEMPLATE/WorkItem rename to .github/ISSUE_TEMPLATE/02-workitem.md From 54a26ba08dd113b359c30185b0ba090fee12a475 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:21:36 +0200 Subject: [PATCH 064/255] scion.sh, topogen: adopt docker compose plugin and cleanup (#4398) Make the build and test environment easier to setup and use: * Obsolete (and slow) docker-compose V1 replaced with V2 compose plugin: * V1 all gone, invoke `docker compose` not `docker-compose` * Made scion.sh mstatus robust wrt docker-compose output formatting and make output more intelligible. * Work-around issue in some V2 versions: set some safe $HOME for python tests that use docker-compose. * Jeager and prometheus now started/stopped in one command and neither is started nor stopped by default. Documentation updated accordingly too. * scion.sh commands are start/stop, not run/stop, all subcommands kebab-case * Doc is a bit clearer regarding supervisor vs docker. * Fixed revocation test to pass -d to end2end-integration when required. * Delete the install_docker script: gets outdated too fast, better refer the user to official docker install instructions. --- .buildkite/hooks/pre-command | 4 +- BUILD.bazel | 1 + Makefile | 4 + acceptance/common/README.md | 2 +- acceptance/common/base.py | 2 +- acceptance/common/docker.py | 3 +- acceptance/common/raw.bzl | 7 + acceptance/common/topogen.bzl | 7 + acceptance/router_multi/BUILD.bazel | 2 + acceptance/sig_short_exp_time/test | 14 +- acceptance/topo_cs_reload/reload_test.go | 21 +-- acceptance/topo_daemon_reload/reload_test.go | 21 +-- acceptance/trc_update/BUILD.bazel | 1 + doc/dev/run.rst | 44 +++++- doc/dev/setup.rst | 9 +- scion.sh | 128 ++++++++---------- tools/await-connectivity | 2 +- tools/dc | 16 +-- tools/install_docker | 48 ------- tools/integration/cmd.go | 2 +- tools/integration/docker.go | 5 +- tools/integration/revocation_test.sh | 9 +- tools/jaeger_ui.sh | 62 +++++++++ tools/topogen.py | 2 +- tools/topology/config.py | 23 ++-- tools/topology/go.py | 2 +- tools/topology/jaeger.py | 70 ---------- .../topology/{prometheus.py => monitoring.py} | 56 ++++++-- tools/topology/sig.py | 2 +- 29 files changed, 289 insertions(+), 280 deletions(-) delete mode 100755 tools/install_docker create mode 100755 tools/jaeger_ui.sh delete mode 100644 tools/topology/jaeger.py rename tools/topology/{prometheus.py => monitoring.py} (76%) diff --git a/.buildkite/hooks/pre-command b/.buildkite/hooks/pre-command index 0650d3644..ada7f07ae 100755 --- a/.buildkite/hooks/pre-command +++ b/.buildkite/hooks/pre-command @@ -43,7 +43,7 @@ echo "~~~ Starting bazel remote cache proxy" # Start bazel remote cache proxy for S3 # Note that S3 keys are injected by buildkite, see # https://buildkite.com/docs/pipelines/secrets#storing-secrets-with-the-elastic-ci-stack-for-aws -docker-compose -f .buildkite/hooks/bazel-remote.yml -p bazel_remote up -d +docker compose --compatibility -f .buildkite/hooks/bazel-remote.yml -p bazel_remote up -d echo "~~~ Starting go module proxy" -docker-compose -f .buildkite/hooks/go-module-proxy.yml -p athens up -d +docker compose --compatibility -f .buildkite/hooks/go-module-proxy.yml -p athens up -d diff --git a/BUILD.bazel b/BUILD.bazel index be76b0e6c..267914fd4 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -245,6 +245,7 @@ updatesrc_update_all( write_source_files( name = "write_all_source_files", additional_update_targets = [ + "//doc/_build/_static/command:write_files", "//doc/command:write_files", ], ) diff --git a/Makefile b/Makefile index 43fe60d30..2cb241940 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,10 @@ clean: bazel clean rm -f bin/* +scrub: + bazel clean --expunge + rm -f bin/* + bazel: rm -f bin/* bazel build //:scion //:scion-ci diff --git a/acceptance/common/README.md b/acceptance/common/README.md index 0ca1fc308..c2759d81b 100644 --- a/acceptance/common/README.md +++ b/acceptance/common/README.md @@ -56,7 +56,7 @@ Tests can use: - `self.artifacts`: the specified directory for test outputs, created during setup. - `self.get_executable()`: returns an executable specified using the `--executable` switch. -- `self.dc`: a wrapper for `docker-compose`, instantiated during `TestTopogen.setup`. +- `self.dc`: a wrapper for `docker compose`, instantiated during `TestTopogen.setup`. The `base.main` function is the main entry point to run the tests and must be invoked in `__main__`. diff --git a/acceptance/common/base.py b/acceptance/common/base.py index dda57be94..204c35f9c 100644 --- a/acceptance/common/base.py +++ b/acceptance/common/base.py @@ -203,7 +203,7 @@ def setup_start(self): raise Exception("Failed services.\n" + ps) def teardown(self): - # Avoid running docker-compose teardown if setup_prepare failed + # Avoid running docker compose teardown if setup_prepare failed if self._setup_prepare_failed: return out_dir = self.artifacts / "logs" diff --git a/acceptance/common/docker.py b/acceptance/common/docker.py index b77a7f8b4..e4a1b7014 100644 --- a/acceptance/common/docker.py +++ b/acceptance/common/docker.py @@ -51,7 +51,8 @@ def __call__(self, *args, **kwargs) -> str: # Note: not using plumbum here due to complications with encodings in the captured output try: res = subprocess.run( - ["docker-compose", "-f", self.compose_file, "-p", self.project, *args], + ["docker", "compose", "--compatibility", + "-f", self.compose_file, "-p", self.project, *args], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8") except subprocess.CalledProcessError as e: raise _CalledProcessErrorWithOutput(e) from None diff --git a/acceptance/common/raw.bzl b/acceptance/common/raw.bzl index 5d8734d7e..2f024ca8d 100644 --- a/acceptance/common/raw.bzl +++ b/acceptance/common/raw.bzl @@ -1,6 +1,11 @@ load("//tools/lint:py.bzl", "py_binary", "py_library", "py_test") load("@com_github_scionproto_scion_python_deps//:requirements.bzl", "requirement") +# Bug in bazel: HOME isn't set to TEST_TMPDIR. +# Bug in docker-compose v2.21 a writable HOME is required (eventhough not used). +# Poor design in Bazel, there's no sane way to obtain the path to some +# location that's not a litteral dependency. +# So, HOME must be provided by the invoker. def raw_test( name, src, @@ -8,6 +13,7 @@ def raw_test( deps = [], data = [], tags = [], + homedir = "", local = False): py_library( name = "%s_lib" % name, @@ -63,5 +69,6 @@ def raw_test( "PYTHONUNBUFFERED": "1", # Ensure that unicode output can be printed to the log/console "PYTHONIOENCODING": "utf-8", + "HOME": homedir, }, ) diff --git a/acceptance/common/topogen.bzl b/acceptance/common/topogen.bzl index cc18515f0..08d90df42 100644 --- a/acceptance/common/topogen.bzl +++ b/acceptance/common/topogen.bzl @@ -1,6 +1,11 @@ load("//tools/lint:py.bzl", "py_binary", "py_library", "py_test") load("@com_github_scionproto_scion_python_deps//:requirements.bzl", "requirement") +# Bug in bazel: HOME isn't set to TEST_TMPDIR. +# Bug in docker-compose v2.21 a writable HOME is required (eventhough not used). +# Poor design in Bazel, there's no sane way to obtain the path to some +# location that's not a litteral dependency. +# So, HOME must be provided by the invoker. def topogen_test( name, src, @@ -10,6 +15,7 @@ def topogen_test( args = [], deps = [], data = [], + homedir = "", tester = "//docker:tester"): """Creates a test based on a topology file. @@ -105,6 +111,7 @@ def topogen_test( "PYTHONUNBUFFERED": "1", # Ensure that unicode output can be printed to the log/console "PYTHONIOENCODING": "utf-8", + "HOME": homedir, }, ) diff --git a/acceptance/router_multi/BUILD.bazel b/acceptance/router_multi/BUILD.bazel index 180901406..762c404da 100644 --- a/acceptance/router_multi/BUILD.bazel +++ b/acceptance/router_multi/BUILD.bazel @@ -30,6 +30,7 @@ raw_test( "--bfd", ], data = data, + homedir = "$(rootpath :router)", # This test uses sudo and accesses /var/run/netns. local = True, ) @@ -39,6 +40,7 @@ raw_test( src = "test.py", args = args, data = data, + homedir = "$(rootpath :router)", # This test uses sudo and accesses /var/run/netns. local = True, ) diff --git a/acceptance/sig_short_exp_time/test b/acceptance/sig_short_exp_time/test index 1908cde8d..10bc25eb2 100755 --- a/acceptance/sig_short_exp_time/test +++ b/acceptance/sig_short_exp_time/test @@ -55,24 +55,24 @@ run_test() {(set -e docker image load -i acceptance/sig_short_exp_time/sig1.tar docker image load -i acceptance/sig_short_exp_time/sig2.tar - docker-compose -f acceptance/sig_short_exp_time/docker-compose.yml up -d dispatcher1 dispatcher2 sig1 sig2 patha pathb + docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml up -d dispatcher1 dispatcher2 sig1 sig2 patha pathb # Set up forward route on network stack 1 and 2 through the sig tunnel # device. The route is a property of the network stack, and persists after # the container that added it has exited. # # If the route configuration fails, the test is not stopped. - docker-compose -f acceptance/sig_short_exp_time/docker-compose.yml run --name route1 --rm tester1 ip route add 242.254.200.2/32 dev sig || true - docker-compose -f acceptance/sig_short_exp_time/docker-compose.yml run --name route2 --rm tester2 ip route add 242.254.100.2/32 dev sig || true + docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml run --name route1 --rm tester1 ip route add 242.254.200.2/32 dev sig || true + docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml run --name route2 --rm tester2 ip route add 242.254.100.2/32 dev sig || true echo "Start background ping, ping every 0.2 seconds" - docker-compose -f acceptance/sig_short_exp_time/docker-compose.yml run --name tester1 -d tester1 ping -i 0.2 242.254.200.2 + docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml run --name tester1 -d tester1 ping -i 0.2 242.254.200.2 echo "Waiting 10 seconds for path A to expire..." sleep 10 echo "Path A expired, simulating it by shutting down path A proxy" # Traffic should have switched beforehand to path b, and no pings should be lost - docker-compose -f acceptance/sig_short_exp_time/docker-compose.yml stop patha + docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml stop patha sleep 1 docker kill -s SIGINT tester1 @@ -104,9 +104,9 @@ OUTPUT_DIR=$TEST_UNDECLARED_OUTPUTS_DIR mkdir -p $OUTPUT_DIR/logs for CNTR in sig1 sig2 dispatcher1 dispatcher2; do - docker-compose -f acceptance/sig_short_exp_time/docker-compose.yml logs "$CNTR" > "$OUTPUT_DIR/logs/$CNTR.log" + docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml logs "$CNTR" > "$OUTPUT_DIR/logs/$CNTR.log" done -docker-compose -f acceptance/sig_short_exp_time/docker-compose.yml down -v +docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml down -v exit $RC diff --git a/acceptance/topo_cs_reload/reload_test.go b/acceptance/topo_cs_reload/reload_test.go index 790f4a012..53186c642 100644 --- a/acceptance/topo_cs_reload/reload_test.go +++ b/acceptance/topo_cs_reload/reload_test.go @@ -108,16 +108,19 @@ func setupTest(t *testing.T) testState { s.mustExec(t, "docker", "image", "load", "-i", "dispatcher.tar") s.mustExec(t, "docker", "image", "load", "-i", "control.tar") // now start the docker containers - s.mustExec(t, "docker-compose", "-f", "docker-compose.yml", "up", "-d") + s.mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + "up", "-d") // wait a bit to make sure the containers are ready. time.Sleep(time.Second / 2) t.Log("Test setup done") - s.mustExec(t, "docker-compose", "-f", "docker-compose.yml", "ps") + s.mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + "ps") return s } func (s testState) teardownTest(t *testing.T) { - defer s.mustExec(t, "docker-compose", "-f", "docker-compose.yml", "down", "-v") + defer s.mustExec(t, "docker", "compose", "--compatibility", + "-f", "docker-compose.yml", "down", "-v") outdir, exists := os.LookupEnv("TEST_UNDECLARED_OUTPUTS_DIR") require.True(t, exists, "TEST_UNDECLARED_OUTPUTS_DIR must be defined") @@ -127,8 +130,8 @@ func (s testState) teardownTest(t *testing.T) { "topo_cs_reload_dispatcher": "disp.log", "topo_cs_reload_control_srv": "control.log", } { - cmd := exec.Command("docker-compose", "-f", "docker-compose.yml", "logs", "--no-color", - service) + cmd := exec.Command("docker", "compose", "--compatibility", + "-f", "docker-compose.yml", "logs", "--no-color", service) logFileName := fmt.Sprintf("%s/logs/%s", outdir, file) logFile, err := os.Create(logFileName) if err != nil { @@ -146,10 +149,10 @@ func (s testState) teardownTest(t *testing.T) { func (s testState) loadTopo(t *testing.T, name string) { t.Helper() - s.mustExec(t, "docker-compose", "-f", "docker-compose.yml", "exec", "-T", - "topo_cs_reload_control_srv", "mv", name, "/topology.json") - s.mustExec(t, "docker-compose", "-f", "docker-compose.yml", "kill", "-s", "SIGHUP", - "topo_cs_reload_control_srv") + s.mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + "exec", "-T", "topo_cs_reload_control_srv", "mv", name, "/topology.json") + s.mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + "kill", "-s", "SIGHUP", "topo_cs_reload_control_srv") } func (s testState) mustExec(t *testing.T, name string, arg ...string) { diff --git a/acceptance/topo_daemon_reload/reload_test.go b/acceptance/topo_daemon_reload/reload_test.go index 243cb133a..ee9b9f44b 100644 --- a/acceptance/topo_daemon_reload/reload_test.go +++ b/acceptance/topo_daemon_reload/reload_test.go @@ -71,16 +71,18 @@ func setupTest(t *testing.T) { mustExec(t, "docker", "image", "load", "-i", "dispatcher.tar") mustExec(t, "docker", "image", "load", "-i", "daemon.tar") // now start the docker containers - mustExec(t, "docker-compose", "-f", "docker-compose.yml", "up", - "-d", "topo_daemon_reload_dispatcher", "topo_daemon_reload_daemon") + mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + "up", "-d", "topo_daemon_reload_dispatcher", "topo_daemon_reload_daemon") // wait a bit to make sure the containers are ready. time.Sleep(time.Second / 2) t.Log("Test setup done") - mustExec(t, "docker-compose", "-f", "docker-compose.yml", "ps") + mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + "ps") } func teardownTest(t *testing.T) { - defer mustExec(t, "docker-compose", "-f", "docker-compose.yml", "down", "-v") + defer mustExec(t, "docker", "compose", "--compatibility", + "-f", "docker-compose.yml", "down", "-v") outdir, exists := os.LookupEnv("TEST_UNDECLARED_OUTPUTS_DIR") require.True(t, exists, "TEST_UNDECLARED_OUTPUTS_DIR must be defined") @@ -90,7 +92,8 @@ func teardownTest(t *testing.T) { "topo_daemon_reload_dispatcher": "disp.log", "topo_daemon_reload_daemon": "daemon.log", } { - cmd := exec.Command("docker-compose", "-f", "docker-compose.yml", "logs", "--no-color", + cmd := exec.Command("docker", "compose", "--compatibility", + "-f", "docker-compose.yml", "logs", "--no-color", service) logFileName := fmt.Sprintf("%s/logs/%s", outdir, file) logFile, err := os.Create(logFileName) @@ -108,10 +111,10 @@ func teardownTest(t *testing.T) { func loadTopo(t *testing.T, name string) { t.Helper() - mustExec(t, "docker-compose", "-f", "docker-compose.yml", "exec", "-T", - "topo_daemon_reload_daemon", "mv", name, "/topology.json") - mustExec(t, "docker-compose", "-f", "docker-compose.yml", "kill", "-s", "SIGHUP", - "topo_daemon_reload_daemon") + mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + "exec", "-T", "topo_daemon_reload_daemon", "mv", name, "/topology.json") + mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + "kill", "-s", "SIGHUP", "topo_daemon_reload_daemon") } func mustExec(t *testing.T, name string, arg ...string) { diff --git a/acceptance/trc_update/BUILD.bazel b/acceptance/trc_update/BUILD.bazel index 4f91062fa..6e8125faf 100644 --- a/acceptance/trc_update/BUILD.bazel +++ b/acceptance/trc_update/BUILD.bazel @@ -7,5 +7,6 @@ topogen_test( "--executable=end2end_integration:$(location //tools/end2end_integration)", ], data = ["//tools/end2end_integration"], + homedir = "$(rootpath //tools/end2end_integration)", topo = "//topology:tiny4.topo", ) diff --git a/doc/dev/run.rst b/doc/dev/run.rst index 77563c6fc..0de92eb3c 100644 --- a/doc/dev/run.rst +++ b/doc/dev/run.rst @@ -14,8 +14,9 @@ Running SCION in this developement setup, is also called running a **local topol The scripts support two different process orchestrators as "backends": - `supervisor `_. This is the default and a bit more light-weight. Packets are sent over the loopback interface. -- `docker-compose `_. Runs individual processes in separate containers connected with docker network bridges. Only this mode supports running a "SCION-IP gateway". +- `docker compose `_. Runs individual processes in separate containers connected with docker network bridges. Only this mode supports running a "SCION-IP gateway". + .. hint:: Before attempting to use the docker compose mode, be sure to build the necessary docker images with ``make docker-images`` .. TODO - Describe configuration directory (referencing manuals) @@ -31,7 +32,7 @@ Quickstart * Build, using ``make`` #. Generate the control-plane PKI keys and certificates, configuration files, and process - orchestrator (supervisor or docker-compose) configuration. + orchestrator (supervisor or docker compose) configuration. .. code-block:: bash @@ -84,6 +85,13 @@ Various helper files are also generated for the benefit of scripts and tooling o for example, ``gen/sciond_addresses.json`` is a simple mapping from AS number to the address of the corresponding :doc:`scion daemon ` instance. +If :option:`scion.sh topology -d` command is used, configuration files are created to +enable running the SCION services in docker containers (see :ref:`docker-section`). Otherwise, +a configuration file is created to enable running the SCION services as plain processes +(see :ref:`supervisor-section`) + +.. _supervisor-section: + supervisor ---------- The ``gen/supervisord.conf`` configuration defines the programs that make up the local topology. @@ -109,16 +117,18 @@ For example:: # and now ping this host from inside AS 1-ff00:0:110, with interactive path prompt bin/scion ping --sciond $(./scion.sh sciond-addr 110) 1-ff00:0:111,127.0.0.1 --interactive +.. _docker-section: + docker ------ -The main docker-compose file is ``gen/scion-dc.yml``. +The main docker compose file is ``gen/scion-dc.yml``. Each SCION service or router runs in a separate container, and the network access of the individual containers is configured to mimick real-world connectivity. There are "tester" containers configured in each AS to mimick end hosts in a SCION AS. These tester containers can be used to run commands accessing the SCION network. -As a shorthand for the somewhat unwieldy ``docker-compose`` invocation, the :file-ref:`tools/dc` +As a shorthand for the somewhat unwieldy ``docker compose`` invocation, the :file-ref:`tools/dc` script can be used. For example:: # show paths from 1-ff00:0:112 to 1-ff00:0:110 @@ -140,7 +150,7 @@ scion.sh .. Note:: The SCION tools and services need to be built **before** running these commands, using - ``make`` or ``make docker-images`` (when using the docker-compose configuration). + ``make`` or ``make docker-images`` (when using the docker compose configuration). The basic usage is ``./scion.sh ``. The main subcommands are: @@ -149,7 +159,7 @@ The basic usage is ``./scion.sh ``. The main subcommands a .. option:: topology Generate the control-plane PKI keys and certificates, configuration files, - and process orchestrator (supervisor or docker-compose) configuration + and process orchestrator (supervisor or docker compose) configuration for a given network topopology defined in a :file-ref:`*.topo configuration file `. @@ -161,7 +171,7 @@ The basic usage is ``./scion.sh ``. The main subcommands a .. option:: -d, --docker - Create a docker-compose configuration (instead of default supervisord). + Create a docker compose configuration (instead of default supervisord). .. option:: --sig @@ -180,6 +190,14 @@ The basic usage is ``./scion.sh ``. The main subcommands a Terminate this run of the local SCION topology. +.. option:: start-monitoring + + Start the monitoring services (jaeger and prometheus). + +.. option:: stop-monitoring + + Stop the monitoring services. + .. option:: sciond-addr Return the address for the scion daemon for the matching ISD-AS by consulting @@ -190,3 +208,15 @@ The basic usage is ``./scion.sh ``. The main subcommands a .. option:: help Describe all available subcommands + +end2end_integration +=================== + +:program:bin/end2end_integration is a basic functional test. + +The basic usage is ``./end2end_integration ``. + +.. option:: -d + + Assume the SCION services are dockerized. Must be consistent with the last + invocation of ``scion.sh topology``. diff --git a/doc/dev/setup.rst b/doc/dev/setup.rst index 53040cec4..dadeb2d69 100644 --- a/doc/dev/setup.rst +++ b/doc/dev/setup.rst @@ -23,9 +23,10 @@ Prerequisites ``sudo usermod -a -G docker ${LOGNAME}``, where ``${LOGNAME}`` is replaced with your user name. Log out and log back in so that your membership of the ``docker`` group is seen by the shell session. - Optionally install ``docker-compose``. This is needed if you want to run the - ``docker-compose`` based test topology setup instead of the default setup based on ``supervisord``. - Please follow the instructions for `docker-compose `_. + Optionally install the ``Docker Compose Plugin``. This is needed if you want to run the + ``docker compose`` based test topology setup instead of the default setup based on ``supervisord``. + Please follow the instructions for + `Install Compose Plugin `_. Bazel ----- @@ -63,7 +64,7 @@ Bazel build artifacts from bazel. Bazel-remote can manage the disk space and does not infinitely grow like the Bazel built-in disk-cache. To start bazel-remote run:: - ./scion.sh bazel_remote + ./scion.sh bazel-remote #. Build SCION services and tools. diff --git a/scion.sh b/scion.sh index c437e3212..cf851d4f6 100755 --- a/scion.sh +++ b/scion.sh @@ -2,16 +2,17 @@ # BEGIN subcommand functions -cmd_bazel_remote() { +cmd_bazel-remote() { mkdir -p "$HOME/.cache/bazel/remote" uid=$(id -u) gid=$(id -g) - USER_ID="$uid" GROUP_ID="$gid" docker-compose -f bazel-remote.yml -p bazel_remote up -d + USER_ID="$uid" GROUP_ID="$gid" docker compose --compatibility -f bazel-remote.yml -p bazel_remote up -d } -cmd_topo_clean() { +cmd_topo-clean() { set -e - cmd_stop || true + stop_scion || true + cmd_stop-monitoring || true rm -rf traces/* mkdir -p logs traces gen gen-cache gen-certs find gen gen-cache gen-certs -mindepth 1 -maxdepth 1 -exec rm -r {} + @@ -19,7 +20,7 @@ cmd_topo_clean() { cmd_topology() { set -e - cmd_topo_clean + cmd_topo-clean echo "Create topology, configuration, and execution files." tools/topogen.py "$@" @@ -32,11 +33,10 @@ cmd_topodot() { ./tools/topodot.py "$@" } -cmd_run() { - run_jaeger +start_scion() { echo "Running the network..." if is_docker_be; then - docker-compose -f gen/scion-dc.yml -p scion up -d + docker compose --compatibility -f gen/scion-dc.yml -p scion up -d return 0 else run_setup @@ -44,6 +44,13 @@ cmd_run() { fi } +cmd_start() { + start_scion + echo "Note that jaeger is no longer started automatically." + echo "To run jaeger and prometheus, use $PROGRAM start-monitoring." + +} + cmd_sciond-addr() { jq -r 'to_entries | map(select(.key | match("'"$1"'";"i"))) | @@ -51,24 +58,26 @@ cmd_sciond-addr() { "[\(.value)]:30255"' gen/sciond_addresses.json } -run_jaeger() { - if [ ! -f "gen/jaeger-dc.yml" ]; then +cmd_start-monitoring() { + if [ ! -f "gen/monitoring-dc.yml" ]; then return fi - echo "Running jaeger..." - ./tools/quiet ./tools/dc jaeger up -d + echo "Running monitoring..." + echo "Jaeger UI: http://localhost:16686" + echo "Prometheus UI: http://localhost:9090" + ./tools/quiet ./tools/dc monitoring up -d } -stop_jaeger() { - if [ ! -f "gen/jaeger-dc.yml" ]; then +cmd_stop-monitoring() { + if [ ! -f "gen/monitoring-dc.yml" ]; then return fi - echo "Stopping jaeger..." - ./tools/quiet ./tools/dc jaeger down -v + echo "Stopping monitoring..." + ./tools/quiet ./tools/dc monitoring down -v } cmd_mstart() { - # Run with docker-compose or supervisor + # Run with docker compose or supervisor if is_docker_be; then services="$(glob_docker "$@")" [ -z "$services" ] && { echo "ERROR: No process matched for $@!"; exit 255; } @@ -99,7 +108,7 @@ run_teardown() { fi } -cmd_stop() { +stop_scion() { echo "Terminating this run of the SCION infrastructure" if is_docker_be; then ./tools/quiet ./tools/dc down @@ -107,7 +116,12 @@ cmd_stop() { ./tools/quiet tools/supervisor.sh shutdown run_teardown fi - stop_jaeger +} + +cmd_stop() { + stop_scion + echo "Note that jaeger is no longer stopped automatically." + echo "To stop jaeger and prometheus, use $PROGRAM stop-monitoring." } cmd_mstop() { @@ -125,25 +139,23 @@ cmd_status() { } cmd_mstatus() { + rscount=0 + tscount=0 if is_docker_be; then services="$(glob_docker "$@")" [ -z "$services" ] && { echo "ERROR: No process matched for $@!"; exit 255; } - out=$(./tools/dc scion ps $services | tail -n +3) - rscount=$(echo "$out" | grep '\' | wc -l) # Number of running services + rscount=$(./tools/dc scion ps --status=running --format "{{.Name}}" $services | wc -l) tscount=$(echo "$services" | wc -w) # Number of all globed services - echo "$out" | grep -v '\' - [ $rscount -eq $tscount ] + ./tools/dc scion ps -a --format "table {{.Name}}\t{{upper .State}}\tuptime {{.RunningFor}}" $services | sed "s/ ago//" | tail -n+2 else - if [ $# -ne 0 ]; then - services="$(glob_supervisor "$@")" - [ -z "$services" ] && { echo "ERROR: No process matched for $@!"; exit 255; } - tools/supervisor.sh status "$services" | grep -v RUNNING - else - tools/supervisor.sh status | grep -v RUNNING - fi - [ $? -eq 1 ] + services="$(glob_supervisor "$@")" + [ -z "$services" ] && { echo "ERROR: No process matched for $@!"; exit 255; } + rscount=$(./tools/supervisor.sh status "$services" | grep RUNNIN | wc -l) + tscount=$(echo "$services" | wc -w) # Number of all globed services + tools/supervisor.sh status "$services" fi # If all tasks are running, then return 0. Else return 1. + [ $rscount -eq $tscount ] return } @@ -187,45 +199,15 @@ is_docker_be() { [ -f gen/scion-dc.yml ] } -traces_name() { - local name=jaeger_read_badger_traces - echo "$name" -} - -cmd_traces() { - set -e - local trace_dir=${1:-"$(readlink -e .)/traces"} - local port=16687 - local name=$(traces_name) - cmd_stop_traces - docker run -d --name "$name" \ - -u "$(id -u):$(id -g)" \ - -e SPAN_STORAGE_TYPE=badger \ - -e BADGER_EPHEMERAL=false \ - -e BADGER_DIRECTORY_VALUE=/badger/data \ - -e BADGER_DIRECTORY_KEY=/badger/key \ - -v "$trace_dir:/badger" \ - -p "$port":16686 \ - jaegertracing/all-in-one:1.22.0 - sleep 3 - x-www-browser "http://localhost:$port" -} - -cmd_stop_traces() { - local name=$(traces_name) - docker stop "$name" || true - docker rm "$name" || true -} - cmd_help() { - cat <<-_EOF + cat <<-_EOF SCION $PROGRAM runs a SCION network locally for development and testing purposes. Two options for process control systems are supported to run the SCION services. - supervisord (default) - - docker-compose + - docker compose This can be selected when initially creating the configuration with the topology subcommand. @@ -236,15 +218,19 @@ cmd_help() { $PROGRAM run Run network. $PROGRAM mstart PROCESS - Start multiple processes + Start multiple processes. $PROGRAM stop Terminate this run of the SCION infrastructure. $PROGRAM mstop PROCESS - Stop multiple processes + Stop multiple processes. + $PROGRAM start-monitoring + Run the monitoring infrastructure. + $PROGRAM stop-monitoring + Terminate this run of the monitoring infrastructure. $PROGRAM status Show all non-running tasks. $PROGRAM mstatus PROCESS - Show status of provided processes + Show status of provided processes. $PROGRAM sciond-addr ISD-AS Return the address for the scion daemon for the matching ISD-AS by consulting gen/sciond_addresses.json. @@ -254,11 +240,7 @@ cmd_help() { Draw a graphviz graph of a *.topo topology configuration file. $PROGRAM help Show this text. - $PROGRAM traces [folder] - Serve jaeger traces from the specified folder (default: traces/) - $PROGRAM stop_traces - Stop the jaeger container started during the traces command - $PROGRAM bazel_remote + $PROGRAM bazel-remote Starts the bazel remote. _EOF } @@ -269,8 +251,8 @@ COMMAND="$1" shift case "$COMMAND" in - help|run|mstart|mstatus|mstop|stop|status|topology|sciond-addr|traces|stop_traces|topo_clean|topodot|bazel_remote) + help|start|start-monitoring|mstart|mstatus|mstop|stop|stop-monitoring|status|topology|sciond-addr|topo-clean|topodot|bazel-remote) "cmd_$COMMAND" "$@" ;; - start) cmd_run "$@" ;; + run) cmd_start "$@" ;; *) cmd_help; exit 1 ;; esac diff --git a/tools/await-connectivity b/tools/await-connectivity index 63ee037e8..4f0d1f2ae 100755 --- a/tools/await-connectivity +++ b/tools/await-connectivity @@ -1,7 +1,7 @@ #!/bin/bash # This script waits for the beaconing process in a local topology (running -# either with supervisor or docker-compose) to establish full connectivity. +# either with supervisor or docker compose) to establish full connectivity. # Uses the control service's segments/ API to determine whether segments have # been registered. # diff --git a/tools/dc b/tools/dc index 7901082a3..a2912882a 100755 --- a/tools/dc +++ b/tools/dc @@ -37,8 +37,8 @@ cmd_help() { - [SERVICE]: As scion service glob, e.g. cs1*. - [GROUP]: - scion: For all scion services. - - prom: For the prometheus service. - - [COMMAND]: A docker-compose command like 'up -d' or 'down' + - monitoring: For the monitoring service (i.e. prometheus and yaeger). + - [COMMAND]: A docker compose command like 'up -d' or 'down' - [IA]: An IA number like 1-ff00:0:110 - [LOG_DIR]: A folder. _EOF @@ -70,12 +70,8 @@ cmd_scion() { dc "scion" "$@" } -cmd_jaeger() { - dc "jaeger" "$@" -} - -cmd_prom() { - dc "prom" "$@" +cmd_monitoring() { + dc "monitoring" "$@" } # Runs docker compose for the given project @@ -83,7 +79,7 @@ dc() { local project="$1" local dc_file="gen/$1-dc.yml" shift - COMPOSE_FILE="$dc_file" docker-compose -p "$project" --ansi never "$@" + COMPOSE_FILE="$dc_file" docker compose --compatibility -p "$project" --ansi never "$@" } cmd_collect_logs() { @@ -135,7 +131,7 @@ COMMAND="$1" shift case "$COMMAND" in - start|stop|down|run|scion|jaeger|prom|collect_logs) + start|stop|down|run|scion|monitoring|collect_logs) "cmd_$COMMAND" "$@" ;; exec_tester) "exec_tester" "$@" ;; diff --git a/tools/install_docker b/tools/install_docker deleted file mode 100755 index 384219a5d..000000000 --- a/tools/install_docker +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -set -e - -[ $(id -u) -eq 0 ] || { echo "Error: this script should be run as root" && exit 1; } - -# Install prereqs -DEBIAN_FRONTEND=noninteractive apt-get install -y apt-transport-https ca-certificates curl lsb-release software-properties-common - -chksum() { - echo "${1:?} ${2:?}" | sha256sum --status -c - -} - -if [ "$(lsb_release -is)" == "LinuxMint" ]; then - release=$(grep UBUNTU_CODENAME /etc/os-release | cut -f2 -d=) -fi -release=${release:-$(lsb_release -cs)} - -# Add docker apt repo. -if ! grep -Rq "https://download.docker.com/linux/ubuntu" /etc/apt/sources.list.d/; then - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - - add-apt-repository "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/ubuntu $release stable" - apt-get update -fi - -# Install docker-ce -DEBIAN_FRONTEND=noninteractive apt-get install -y docker-ce docker-ce-cli containerd.io - -# Install docker-compose v2.5.1 -case "$(uname -m)" in - x86_64) - src=https://github.com/docker/compose/releases/download/v2.5.1/docker-compose-linux-x86_64 - sum=d99de1ea7616f2a4c7914d37674f0650660a5e832be555805a71c0fc377233c9 - file=/usr/libexec/docker/cli-plugins/docker-compose - ;; - *) - echo "ERROR: unsupported architecture '$(uname -m)'" - exit 1 -esac -# If the file doesn't exist, or the checksum fails, (re)download it. -if [ ! -e "$file" ] || ! chksum $sum $file; then - curl -sSL "$src" -o "$file" - chksum $sum $file || { echo "Error: $file doesn't match the expected checksum. ($sum)"; exit 1; } -fi -chmod +x "$file" - -# Install docker-compose switch. -curl -fL https://raw.githubusercontent.com/docker/compose-switch/master/install_on_linux.sh | sh diff --git a/tools/integration/cmd.go b/tools/integration/cmd.go index 5b666d781..e93b92099 100644 --- a/tools/integration/cmd.go +++ b/tools/integration/cmd.go @@ -75,7 +75,7 @@ func Run(ctx context.Context, cfg RunConfig) error { if cfg.Tester != "" { args := append([]string{}, dockerArgs...) args = append(args, cfg.Tester, "sh", "-c", joinCmds(cfg.Commands)) - cmd = exec.CommandContext(ctx, "docker-compose", args...) + cmd = exec.CommandContext(ctx, "docker", args...) log.Debug("Running docker command", "cmd", cmd) } else { cmd = exec.CommandContext(ctx, "sh", "-c", joinCmds(cfg.Commands)) diff --git a/tools/integration/docker.go b/tools/integration/docker.go index e154ab264..055c39183 100644 --- a/tools/integration/docker.go +++ b/tools/integration/docker.go @@ -27,7 +27,7 @@ import ( ) const ( - dockerCmd = "docker-compose" + dockerCmd = "docker" ) var ( @@ -38,7 +38,8 @@ var ( var dockerArgs []string func initDockerArgs() { - dockerArgs = []string{"-f", GenFile("scion-dc.yml"), "-p", "scion", "exec", "-T", "-e", + dockerArgs = []string{"compose", "--compatibility", + "-f", GenFile("scion-dc.yml"), "-p", "scion", "exec", "-T", "-e", fmt.Sprintf("%s=1", GoIntegrationEnv)} } diff --git a/tools/integration/revocation_test.sh b/tools/integration/revocation_test.sh index 9215c9ed6..ac7830927 100755 --- a/tools/integration/revocation_test.sh +++ b/tools/integration/revocation_test.sh @@ -27,14 +27,19 @@ done # Bring down routers. echo "Revocation test" -echo "Stopping routers and waiting for ${SLEEP}s." +echo "Stopping routers and waiting for 4s." ./scion.sh mstop $REV_BRS if [ $? -ne 0 ]; then echo "Failed stopping routers." exit 1 fi sleep 4 + +if [ -f gen/scion-dc.yml ]; then + DOCKER_ARGS="-d" +fi + # Do another round of e2e test with retries echo "Testing connectivity between all the hosts (with retries)." -bin/end2end_integration -log.console info -attempts 15 -subset 1-ff00:0:131#2-ff00:0:222 $DOCKER_ARGS +bin/end2end_integration $DOCKER_ARGS -log.console info -attempts 15 -subset 1-ff00:0:131#2-ff00:0:222 exit $? diff --git a/tools/jaeger_ui.sh b/tools/jaeger_ui.sh new file mode 100755 index 000000000..071d4c246 --- /dev/null +++ b/tools/jaeger_ui.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# BEGIN subcommand functions + +traces_name() { + echo "jaeger_read_badger_traces" +} + +cmd_start() { + set -e + local trace_dir=${1:-"$(readlink -e .)/traces"} + local port=16687 + local name=$(traces_name) + cmd_stop + docker run -d --name "$name" \ + -u "$(id -u):$(id -g)" \ + -e SPAN_STORAGE_TYPE=badger \ + -e BADGER_EPHEMERAL=false \ + -e BADGER_DIRECTORY_VALUE=/badger/data \ + -e BADGER_DIRECTORY_KEY=/badger/key \ + -v "$trace_dir:/badger" \ + -p "$port":16686 \ + jaegertracing/all-in-one:1.22.0 + sleep 3 + echo "Jaeger UI: http://localhost:$port" +} + +cmd_stop() { + local name=$(traces_name) + docker stop "$name" || true + docker rm "$name" || true +} + +cmd_help() { + cat <<-_EOF + $PROGRAM is a helper script to start and stop a stand-alone jaeger UI. + It does not initiate any jaeger trace collection and shows whatever + traces happen to be in the given directory; not necessarily scion traces. + + If you mean to initiate SCION jaeger traces (and look at them), use + scion.sh start-traces instead. + + Usage: + $PROGRAM start + Serve jaeger traces from the default folder: traces/. + $PROGRAM start [folder] + Serve jaeger traces from the specified folder. + $PROGRAM stop + Stop the jaeger container started with start command. + _EOF +} +# END subcommand functions + +PROGRAM="${0##*/}" +COMMAND="$1" +shift + +case "$COMMAND" in + help|start|stop) + "cmd_$COMMAND" "$@" ;; + *) cmd_help; exit 1 ;; +esac diff --git a/tools/topogen.py b/tools/topogen.py index 209dc75e0..eb57e9e8a 100755 --- a/tools/topogen.py +++ b/tools/topogen.py @@ -35,7 +35,7 @@ def add_arguments(parser): parser.add_argument('-c', '--topo-config', default=DEFAULT_TOPOLOGY_FILE, help='Path policy file') parser.add_argument('-d', '--docker', action='store_true', - help='Create a docker-compose configuration') + help='Create a docker compose configuration') parser.add_argument('-n', '--network', help='Network to create subnets in (E.g. "127.0.0.0/8"') parser.add_argument('-o', '--output-dir', default=GEN_PATH, diff --git a/tools/topology/config.py b/tools/topology/config.py index 5fcabb91c..aa70bfbb2 100644 --- a/tools/topology/config.py +++ b/tools/topology/config.py @@ -38,14 +38,13 @@ from topology.common import ArgsBase from topology.docker import DockerGenArgs, DockerGenerator from topology.go import GoGenArgs, GoGenerator -from topology.jaeger import JaegerGenArgs, JaegerGenerator from topology.net import ( NetworkDescription, IPNetwork, SubnetGenerator, DEFAULT_NETWORK, ) -from topology.prometheus import PrometheusGenArgs, PrometheusGenerator +from topology.monitoring import MonitoringGenArgs, MonitoringGenerator from topology.supervisor import SupervisorGenArgs, SupervisorGenerator from topology.topo import TopoGenArgs, TopoGenerator @@ -113,8 +112,7 @@ def _generate_with_topo(self, topo_dicts): self._generate_docker(topo_dicts) else: self._generate_supervisor(topo_dicts) - self._generate_jaeger(topo_dicts) - self._generate_prom_conf(topo_dicts) + self._generate_monitoring_conf(topo_dicts) self._generate_certs_trcs(topo_dicts) def _generate_certs_trcs(self, topo_dicts): @@ -135,11 +133,6 @@ def _generate_go(self, topo_dicts): def _go_args(self, topo_dicts): return GoGenArgs(self.args, self.topo_config, topo_dicts, self.networks) - def _generate_jaeger(self, topo_dicts): - args = JaegerGenArgs(self.args, topo_dicts) - jaeger_gen = JaegerGenerator(args) - jaeger_gen.generate() - def _generate_topology(self): topo_gen = TopoGenerator(self._topo_args()) return topo_gen.generate() @@ -164,13 +157,13 @@ def _generate_docker(self, topo_dicts): def _docker_args(self, topo_dicts): return DockerGenArgs(self.args, topo_dicts, self.all_networks) - def _generate_prom_conf(self, topo_dicts): - args = self._prometheus_args(topo_dicts) - prom_gen = PrometheusGenerator(args) - prom_gen.generate() + def _generate_monitoring_conf(self, topo_dicts): + args = self._monitoring_args(topo_dicts) + mon_gen = MonitoringGenerator(args) + mon_gen.generate() - def _prometheus_args(self, topo_dicts): - return PrometheusGenArgs(self.args, topo_dicts, self.networks) + def _monitoring_args(self, topo_dicts): + return MonitoringGenArgs(self.args, topo_dicts, self.networks) def _write_ca_files(self, topo_dicts, ca_files): isds = set() diff --git a/tools/topology/go.py b/tools/topology/go.py index 36c82537e..d8f06f605 100644 --- a/tools/topology/go.py +++ b/tools/topology/go.py @@ -38,7 +38,7 @@ from topology.net import socket_address_str, NetworkDescription, IPNetwork -from topology.prometheus import ( +from topology.monitoring import ( CS_PROM_PORT, DEFAULT_BR_PROM_PORT, SCIOND_PROM_PORT, diff --git a/tools/topology/jaeger.py b/tools/topology/jaeger.py deleted file mode 100644 index 7355694c5..000000000 --- a/tools/topology/jaeger.py +++ /dev/null @@ -1,70 +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. - -import os -import yaml - -from topology.util import write_file -from topology.common import ( - ArgsTopoDicts, -) - -JAEGER_DC = 'jaeger-dc.yml' - - -class JaegerGenArgs(ArgsTopoDicts): - pass - - -class JaegerGenerator(object): - - def __init__(self, args): - self.args = args - output_base = os.environ.get('SCION_OUTPUT_BASE', os.getcwd()) - self.local_jaeger_dir = os.path.join('traces') - self.docker_jaeger_dir = os.path.join(output_base, self.local_jaeger_dir) - - def generate(self): - dc_conf = self._generate_dc() - os.makedirs(os.path.join(self.local_jaeger_dir, 'data'), exist_ok=True) - os.makedirs(os.path.join(self.local_jaeger_dir, 'key'), exist_ok=True) - write_file(os.path.join(self.args.output_dir, JAEGER_DC), - yaml.dump(dc_conf, default_flow_style=False)) - - def _generate_dc(self): - name = 'jaeger' - entry = { - 'version': '2', - 'services': { - 'jaeger': { - 'image': 'jaegertracing/all-in-one:1.22.0', - 'container_name': name, - 'user': '%s:%s' % (str(os.getuid()), str(os.getgid())), - 'ports': [ - '6831:6831/udp', - '16686:16686' - ], - 'environment': [ - 'SPAN_STORAGE_TYPE=badger', - 'BADGER_EPHEMERAL=false', - 'BADGER_DIRECTORY_VALUE=/badger/data', - 'BADGER_DIRECTORY_KEY=/badger/key', - ], - 'volumes': [ - '%s:/badger:rw' % self.docker_jaeger_dir, - ], - } - } - } - return entry diff --git a/tools/topology/prometheus.py b/tools/topology/monitoring.py similarity index 76% rename from tools/topology/prometheus.py rename to tools/topology/monitoring.py index 9a896a64f..60ac56007 100644 --- a/tools/topology/prometheus.py +++ b/tools/topology/monitoring.py @@ -1,5 +1,7 @@ # Copyright 2014 ETH Zurich # Copyright 2018 ETH Zurich, Anapaya Systems +# Copyright 2019 Anapaya Systems +# Copyright 2023 SCION Association # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,9 +15,10 @@ # See the License for the specific language governing permissions and # limitations under the License. """ -:mod:`prometheus` --- SCION topology prometheus generator -============================================= +:mod:`monitoring` --- SCION topology monitoring generator +========================================================= """ + # Stdlib import os from collections import defaultdict @@ -43,17 +46,16 @@ SIG_PROM_PORT = 30456 DISP_PROM_PORT = 30441 DEFAULT_BR_PROM_PORT = 30442 - -PROM_DC_FILE = "prom-dc.yml" +MONITORING_DC_FILE = "monitoring-dc.yml" -class PrometheusGenArgs(ArgsTopoDicts): +class MonitoringGenArgs(ArgsTopoDicts): def __init__(self, args, topo_dicts, networks: Mapping[IPNetwork, NetworkDescription]): super().__init__(args, topo_dicts) self.networks = networks -class PrometheusGenerator(object): +class MonitoringGenerator(object): PROM_DIR = "prometheus" TARGET_FILES = { "BorderRouters": "br.yml", @@ -70,10 +72,12 @@ class PrometheusGenerator(object): def __init__(self, args): """ - :param PrometheusGenArgs args: Contains the passed command line arguments and topo dicts. + :param MonitoringGenArgs args: Contains the passed command line arguments and topo dicts. """ self.args = args self.output_base = os.environ.get('SCION_OUTPUT_BASE', os.getcwd()) + self.local_jaeger_dir = os.path.join('traces') + self.docker_jaeger_dir = os.path.join(self.output_base, self.local_jaeger_dir) def generate(self): config_dict = {} @@ -99,7 +103,12 @@ def generate(self): self._write_dc_file() self._write_disp_file() + # For yeager + os.makedirs(os.path.join(self.local_jaeger_dir, 'data'), exist_ok=True) + os.makedirs(os.path.join(self.local_jaeger_dir, 'key'), exist_ok=True) + def _write_config_files(self, config_dict): + # For Prometheus targets_paths = defaultdict(list) for topo_id, ele_dict in config_dict.items(): base = topo_id.base_dir(self.args.output_dir) @@ -143,26 +152,45 @@ def _write_disp_file(self): if self.args.docker: return targets_path = os.path.join(self.args.output_dir, "dispatcher", - PrometheusGenerator.PROM_DIR, "disp.yml") + self.PROM_DIR, "disp.yml") target_config = [{'targets': [prom_addr_dispatcher(False, None, None, DISP_PROM_PORT, None)]}] write_file(targets_path, yaml.dump(target_config, default_flow_style=False)) def _write_dc_file(self): - name = 'prometheus' - prom_dc = { + # Merged yeager and prometheus files. + name = 'monitoring' + monitoring_dc = { 'version': DOCKER_COMPOSE_CONFIG_VERSION, 'services': { - name: { + 'prometheus': { 'image': 'prom/prometheus:v2.6.0', - 'container_name': name, + 'container_name': name+'prometheus', 'network_mode': 'host', 'volumes': [ self.output_base + '/gen:/prom-config:ro' ], 'command': ['--config.file', '/prom-config/prometheus.yml'], + }, + 'jaeger': { + 'image': 'jaegertracing/all-in-one:1.22.0', + 'container_name': name+'yeager', + 'user': '%s:%s' % (str(os.getuid()), str(os.getgid())), + 'ports': [ + '6831:6831/udp', + '16686:16686' + ], + 'environment': [ + 'SPAN_STORAGE_TYPE=badger', + 'BADGER_EPHEMERAL=false', + 'BADGER_DIRECTORY_VALUE=/badger/data', + 'BADGER_DIRECTORY_KEY=/badger/key', + ], + 'volumes': [ + '%s:/badger:rw' % self.docker_jaeger_dir, + ], } } } - write_file(os.path.join(self.args.output_dir, PROM_DC_FILE), - yaml.dump(prom_dc, default_flow_style=False)) + write_file(os.path.join(self.args.output_dir, MONITORING_DC_FILE), + yaml.dump(monitoring_dc, default_flow_style=False)) diff --git a/tools/topology/sig.py b/tools/topology/sig.py index eb7855c0a..9ddd2121e 100644 --- a/tools/topology/sig.py +++ b/tools/topology/sig.py @@ -29,7 +29,7 @@ translate_features, ) from topology.net import socket_address_str -from topology.prometheus import SIG_PROM_PORT +from topology.monitoring import SIG_PROM_PORT class SIGGenArgs(ArgsBase): From 1774cbfccb4cd3814906034e28c802f4dd17c4e3 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Tue, 10 Oct 2023 09:43:08 +0200 Subject: [PATCH 065/255] slayers: unmap IPv4-mapped IPv6 addresses (#4377) The Go standard library can produce IPv4-mapped IPv6 addresses when resolving IP addresses. These IP addresses need to be unmapped before putting them on the wire. Before this patch, we could observe the following with tshark: Len=1304 SCION 1-ff00:0:110,[::ffff:172.20.2.2] -> 1-ff00:0:111,[::ffff:172.20.3.2] UDP 32769 -> 32768 1208 The regression was introduced in #4346, which removed the unmapping behavior in slayers.PackAddr. This patch restores the behavior to ensure only unmapped IPv4 addresses make it on the wire. Handling the unmapping in the code that generates the addresses and only checking this in slayers would seem ideal, but these calls are often very far away from the place that would then trigger an error. Thus handling this in slayers seems like a compromise that saves us and the users of the slayers package a lot of trouble. --- pkg/slayers/scion.go | 9 +++++---- pkg/slayers/scion_test.go | 15 +++++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/pkg/slayers/scion.go b/pkg/slayers/scion.go index 7e24772f1..66ff20c75 100644 --- a/pkg/slayers/scion.go +++ b/pkg/slayers/scion.go @@ -394,15 +394,16 @@ func ParseAddr(addrType AddrType, raw []byte) (addr.Host, error) { func PackAddr(host addr.Host) (AddrType, []byte, error) { switch host.Type() { case addr.HostTypeIP: - ip := host.IP() + // The IP is potentially IPv4-in-IPv6. We need to unmap it to ensure + // we only have true IPv4 or IPv6 addresses. + ip := host.IP().Unmap() if !ip.IsValid() { break } - t := T4Ip if ip.Is6() { - t = T16Ip + return T16Ip, ip.AsSlice(), nil } - return t, ip.AsSlice(), nil + return T4Ip, ip.AsSlice(), nil case addr.HostTypeSVC: raw := make([]byte, 4) binary.BigEndian.PutUint16(raw, uint16(host.SVC())) diff --git a/pkg/slayers/scion_test.go b/pkg/slayers/scion_test.go index 06d496755..a79458761 100644 --- a/pkg/slayers/scion_test.go +++ b/pkg/slayers/scion_test.go @@ -33,10 +33,11 @@ import ( ) var ( - ip6Addr = addr.MustParseHost("2001:db8::68") - ip4Addr = addr.MustParseHost("10.0.0.100") - svcAddr = addr.MustParseHost("Wildcard") - rawPath = func() []byte { + ip6Addr = addr.MustParseHost("2001:db8::68") + ip4Addr = addr.MustParseHost("10.0.0.100") + ip4in6Addr = addr.MustParseHost("::ffff:10.0.0.100") + svcAddr = addr.MustParseHost("Wildcard") + rawPath = func() []byte { return []byte("\x00\x00\x20\x80\x00\x00\x01\x11\x00\x00\x01\x00\x01\x00\x02\x22\x00" + "\x00\x01\x00\x00\x3f\x00\x01\x00\x00\x01\x02\x03\x04\x05\x06\x00\x3f\x00\x03\x00" + "\x02\x01\x02\x03\x04\x05\x06\x00\x3f\x00\x00\x00\x02\x01\x02\x03\x04\x05\x06\x00" + @@ -311,6 +312,12 @@ func TestPackAddr(t *testing.T) { rawAddr: ip4Addr.IP().AsSlice(), errorFunc: assert.NoError, }, + "pack IPv4-mapped IPv6": { + addr: ip4in6Addr, + addrType: slayers.T4Ip, + rawAddr: []byte{0xa, 0x0, 0x0, 0x64}, + errorFunc: assert.NoError, + }, "pack IPv6": { addr: ip6Addr, addrType: slayers.T16Ip, From b3fb01d70749810725a6dbbd9c6a7a11553c4c80 Mon Sep 17 00:00:00 2001 From: Edoardo Ottavianelli Date: Thu, 12 Oct 2023 10:40:40 +0200 Subject: [PATCH 066/255] doc: fix typos in overview.rst (#4419) Update overview.rst (typos) --- doc/overview.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/overview.rst b/doc/overview.rst index 93203eb4c..5369826ac 100644 --- a/doc/overview.rst +++ b/doc/overview.rst @@ -55,7 +55,7 @@ Routing is based on the ISD-AS tuple, agnostic of endpoint addressing. ISD numbers are 16-bit identifiers. The 48-bit AS numbers are globally unique, and use a superset of the existing BGP AS numbering scheme. -Formatting rules and and allocations are is currently described in `wiki page "ISD and AS numbering" `_. +Formatting rules and allocations are currently described in `wiki page "ISD and AS numbering" `_. The endpoint local address is not used for inter-domain routing or forwarding, does not need to be globally unique, and can thus be an IPv4, IPv6, or MAC address, for example. From 734f90919732f22dc07fb1026a6cac518708fbc6 Mon Sep 17 00:00:00 2001 From: Sebastian Leisinger Date: Thu, 12 Oct 2023 10:58:33 +0200 Subject: [PATCH 067/255] cppki: limit segment expiration by certificate lifetime (#4369) Update the `beaconing.DefaultExtender` to not create Segments with expiration date that is later than the current AS certificate expiration. Instead the extender uses `min(segmentExpiration, certificateExpiration)` when creating an AS Hop. Contributes to #4286 --- control/beaconing/BUILD.bazel | 2 + control/beaconing/extender.go | 64 +++++++--- control/beaconing/extender_test.go | 114 ++++++++++++++++-- control/beaconing/originator_test.go | 4 +- control/beaconing/propagator_test.go | 6 +- control/beaconing/writer_test.go | 16 ++- control/cmd/control/main.go | 2 +- control/mgmtapi/testdata/TestAPI_beacon | 2 +- .../mgmtapi/testdata/TestAPI_beacon_id_prefix | 2 +- control/mgmtapi/testdata/TestAPI_beacons | 4 +- .../testdata/TestAPI_beacons_descending_order | 4 +- .../testdata/TestAPI_beacons_existing_usages | 2 +- .../TestAPI_beacons_sort_by_ingress_interface | 4 +- control/observability.go | 10 ++ control/tasks.go | 20 ++- .../hiddenpath/beaconwriter_test.go | 12 +- pkg/segment/seg.go | 2 +- pkg/slayers/path/hopfield.go | 23 +++- pkg/slayers/path/hopfield_test.go | 47 ++++++++ private/app/appnet/intra_as.go | 2 +- .../segments/api/testdata/segments-by-id.json | 2 +- private/path/combinator/expiry_test.go | 12 +- private/path/combinator/graph.go | 2 +- private/segment/segfetcher/pather.go | 2 +- 24 files changed, 297 insertions(+), 63 deletions(-) diff --git a/control/beaconing/BUILD.bazel b/control/beaconing/BUILD.bazel index d3123fdd6..9d3233939 100644 --- a/control/beaconing/BUILD.bazel +++ b/control/beaconing/BUILD.bazel @@ -37,6 +37,7 @@ go_library( "//private/segment/verifier:go_default_library", "//private/topology:go_default_library", "//private/tracing:go_default_library", + "//private/trust:go_default_library", "@com_github_opentracing_opentracing_go//:go_default_library", ], ) @@ -70,6 +71,7 @@ go_test( "//pkg/scrypto/signed:go_default_library", "//pkg/segment:go_default_library", "//pkg/segment/extensions/staticinfo:go_default_library", + "//pkg/slayers/path:go_default_library", "//pkg/slayers/path/scion:go_default_library", "//pkg/snet:go_default_library", "//pkg/snet/addrutil:go_default_library", diff --git a/control/beaconing/extender.go b/control/beaconing/extender.go index 7e5fe00a4..cf440eaa1 100644 --- a/control/beaconing/extender.go +++ b/control/beaconing/extender.go @@ -23,14 +23,22 @@ import ( "github.com/scionproto/scion/control/ifstate" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/metrics" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/private/util" seg "github.com/scionproto/scion/pkg/segment" "github.com/scionproto/scion/pkg/segment/extensions/digest" "github.com/scionproto/scion/pkg/segment/extensions/epic" "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/private/trust" ) +// SignerGen generates signers and returns their expiration time. +type SignerGen interface { + // Generate generates a signer it. + Generate(ctx context.Context) (trust.Signer, error) +} + // Extender extends path segments. type Extender interface { // Extend extends the path segment. The zero value for ingress indicates @@ -44,8 +52,8 @@ type Extender interface { type DefaultExtender struct { // IA is the local IA IA addr.IA - // Signer is used to sign path segments. - Signer seg.Signer + // SignerGen is used to sign path segments. + SignerGen SignerGen // MAC is used to calculate the hop field MAC. MAC func() hash.Hash // Intfs holds all interfaces in the AS. @@ -60,6 +68,11 @@ type DefaultExtender struct { StaticInfo func() *StaticInfoCfg // EPIC defines whether the EPIC authenticators should be added when the segment is extended. EPIC bool + + // SegmentExpirationDeficient is a gauge that is set to 1 if the expiration time of the segment + // is below the maximum expiration time. This happens when the signer expiration time is lower + // than the maximum segment expiration time. + SegmentExpirationDeficient metrics.Gauge } // Extend extends the beacon with hop fields. @@ -85,8 +98,27 @@ func (s *DefaultExtender) Extend( } ts := pseg.Info.Timestamp + signer, err := s.SignerGen.Generate(ctx) + if err != nil { + return serrors.WrapStr("getting signer", err) + } + // Make sure the hop expiration time is not longer than the signer expiration time. + expTime := s.MaxExpTime() + if ts.Add(path.ExpTimeToDuration(expTime)).After(signer.Expiration) { + metrics.GaugeSet(s.SegmentExpirationDeficient, 1) + var err error + expTime, err = path.ExpTimeFromDuration(signer.Expiration.Sub(ts)) + if err != nil { + return serrors.WrapStr( + "calculating expiry time from signer expiration time", err, + "signer_expiration", signer.Expiration, + ) + } + } else { + metrics.GaugeSet(s.SegmentExpirationDeficient, 0) + } hopBeta := extractBeta(pseg) - hopEntry, epicHopMac, err := s.createHopEntry(ingress, egress, ts, hopBeta) + hopEntry, epicHopMac, err := s.createHopEntry(ingress, egress, expTime, ts, hopBeta) if err != nil { return serrors.WrapStr("creating hop entry", err) } @@ -104,7 +136,7 @@ func (s *DefaultExtender) Extend( // is traversed. peerBeta := hopBeta ^ binary.BigEndian.Uint16(hopEntry.HopField.MAC[:2]) - peerEntries, epicPeerMacs, err := s.createPeerEntries(egress, peers, ts, peerBeta) + peerEntries, epicPeerMacs, err := s.createPeerEntries(egress, peers, expTime, ts, peerBeta) if err != nil { return err } @@ -143,7 +175,7 @@ func (s *DefaultExtender) Extend( } } - if err := pseg.AddASEntry(ctx, asEntry, s.Signer); err != nil { + if err := pseg.AddASEntry(ctx, asEntry, signer); err != nil { return err } if egress == 0 { @@ -153,12 +185,12 @@ func (s *DefaultExtender) Extend( } func (s *DefaultExtender) createPeerEntries(egress uint16, peers []uint16, - ts time.Time, beta uint16) ([]seg.PeerEntry, [][]byte, error) { + expTime uint8, ts time.Time, beta uint16) ([]seg.PeerEntry, [][]byte, error) { peerEntries := make([]seg.PeerEntry, 0, len(peers)) peerEpicMacs := make([][]byte, 0, len(peers)) for _, peer := range peers { - peerEntry, epicMac, err := s.createPeerEntry(peer, egress, ts, beta) + peerEntry, epicMac, err := s.createPeerEntry(peer, egress, expTime, ts, beta) if err != nil { log.Debug("Ignoring peer link upon error", "task", s.Task, "peer_interface", peer, "err", err) @@ -170,15 +202,20 @@ func (s *DefaultExtender) createPeerEntries(egress uint16, peers []uint16, return peerEntries, peerEpicMacs, nil } -func (s *DefaultExtender) createHopEntry(ingress, egress uint16, ts time.Time, - beta uint16) (seg.HopEntry, []byte, error) { +func (s *DefaultExtender) createHopEntry( + ingress, + egress uint16, + expTime uint8, + ts time.Time, + beta uint16, +) (seg.HopEntry, []byte, error) { remoteInMTU, err := s.remoteMTU(ingress) if err != nil { return seg.HopEntry{}, nil, serrors.WrapStr("checking remote ingress interface (mtu)", err, "interfaces", ingress) } - hopF, epicMac := s.createHopF(ingress, egress, ts, beta) + hopF, epicMac := s.createHopF(ingress, egress, expTime, ts, beta) return seg.HopEntry{ IngressMTU: int(remoteInMTU), HopField: seg.HopField{ @@ -190,7 +227,7 @@ func (s *DefaultExtender) createHopEntry(ingress, egress uint16, ts time.Time, }, epicMac, nil } -func (s *DefaultExtender) createPeerEntry(ingress, egress uint16, ts time.Time, +func (s *DefaultExtender) createPeerEntry(ingress, egress uint16, expTime uint8, ts time.Time, beta uint16) (seg.PeerEntry, []byte, error) { remoteInIA, remoteInIfID, remoteInMTU, err := s.remoteInfo(ingress) @@ -198,7 +235,7 @@ func (s *DefaultExtender) createPeerEntry(ingress, egress uint16, ts time.Time, return seg.PeerEntry{}, nil, serrors.WrapStr("checking remote ingress interface", err, "ingress_interface", ingress) } - hopF, epicMac := s.createHopF(ingress, egress, ts, beta) + hopF, epicMac := s.createHopF(ingress, egress, expTime, ts, beta) return seg.PeerEntry{ PeerMTU: int(remoteInMTU), Peer: remoteInIA, @@ -259,10 +296,9 @@ func (s *DefaultExtender) remoteInfo(ifid uint16) ( return topoInfo.IA, topoInfo.RemoteID, topoInfo.MTU, nil } -func (s *DefaultExtender) createHopF(ingress, egress uint16, ts time.Time, +func (s *DefaultExtender) createHopF(ingress, egress uint16, expTime uint8, ts time.Time, beta uint16) (path.HopField, []byte) { - expTime := s.MaxExpTime() input := make([]byte, path.MACBufferSize) path.MACInput(beta, util.TimeToSecs(ts), expTime, ingress, egress, input) diff --git a/control/beaconing/extender_test.go b/control/beaconing/extender_test.go index 99163a683..cfd0a72a3 100644 --- a/control/beaconing/extender_test.go +++ b/control/beaconing/extender_test.go @@ -36,7 +36,9 @@ import ( cryptopb "github.com/scionproto/scion/pkg/proto/crypto" "github.com/scionproto/scion/pkg/scrypto" seg "github.com/scionproto/scion/pkg/segment" + "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/private/topology" + "github.com/scionproto/scion/private/trust" ) func TestDefaultExtenderExtend(t *testing.T) { @@ -98,8 +100,8 @@ func TestDefaultExtenderExtend(t *testing.T) { intfs.Get(peer).Activate(peerRemoteIfs[peer]) } ext := &beaconing.DefaultExtender{ - IA: topo.IA(), - Signer: testSigner(t, priv, topo.IA()), + IA: topo.IA(), + SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())}, MAC: func() hash.Hash { mac, err := scrypto.InitMac(make([]byte, 16)) require.NoError(t, err) @@ -171,8 +173,8 @@ func TestDefaultExtenderExtend(t *testing.T) { intfs := ifstate.NewInterfaces(interfaceInfos(topo), ifstate.Config{}) require.NoError(t, err) ext := &beaconing.DefaultExtender{ - IA: topo.IA(), - Signer: testSigner(t, priv, topo.IA()), + IA: topo.IA(), + SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())}, MAC: func() hash.Hash { mac, err := scrypto.InitMac(make([]byte, 16)) require.NoError(t, err) @@ -189,8 +191,106 @@ func TestDefaultExtenderExtend(t *testing.T) { err = ext.Extend(context.Background(), pseg, 0, graph.If_111_A_112_X, []uint16{}) require.NoError(t, err) assert.Equal(t, uint8(1), pseg.ASEntries[0].HopEntry.HopField.ExpTime) - }) + t.Run("segment and signer expiration interaction", func(t *testing.T) { + ts := time.Now() + testCases := map[string]struct { + SignerGen beaconing.SignerGen + MaxExpTime func() uint8 + ExpTime uint8 + ErrAssertion assert.ErrorAssertionFunc + }{ + "signer expires before max expiration time": { + SignerGen: testSignerGen{ + Signer: func() trust.Signer { + s := testSigner(t, priv, topo.IA()) + s.Expiration = ts.Add(path.MaxTTL / 2) + return s + }(), + }, + ExpTime: 127, + MaxExpTime: func() uint8 { return 255 }, + ErrAssertion: assert.NoError, + }, + "signer expires after max expiration time": { + SignerGen: testSignerGen{ + Signer: func() trust.Signer { + s := testSigner(t, priv, topo.IA()) + s.Expiration = ts.Add(path.MaxTTL) + return s + }(), + }, + ExpTime: 254, + MaxExpTime: func() uint8 { return 254 }, + ErrAssertion: assert.NoError, + }, + "minimum signer expiration time": { + SignerGen: testSignerGen{ + Signer: func() trust.Signer { + s := testSigner(t, priv, topo.IA()) + s.Expiration = ts.Add(path.MaxTTL / 256) + return s + }(), + }, + ExpTime: 0, + MaxExpTime: func() uint8 { return 10 }, + ErrAssertion: assert.NoError, + }, + "signer expiration time too small": { + SignerGen: testSignerGen{ + Signer: func() trust.Signer { + s := testSigner(t, priv, topo.IA()) + s.Expiration = ts.Add(path.MaxTTL / 257) + return s + }(), + }, + MaxExpTime: func() uint8 { return 10 }, + ErrAssertion: assert.Error, + }, + "signer expiration time too large uses MaxExpTime": { + SignerGen: testSignerGen{ + Signer: func() trust.Signer { + s := testSigner(t, priv, topo.IA()) + s.Expiration = ts.Add(2 * path.MaxTTL) + return s + }(), + }, + ExpTime: 157, + MaxExpTime: func() uint8 { return 157 }, + ErrAssertion: assert.NoError, + }, + } + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + mctrl := gomock.NewController(t) + defer mctrl.Finish() + intfs := ifstate.NewInterfaces(interfaceInfos(topo), ifstate.Config{}) + require.NoError(t, err) + ext := &beaconing.DefaultExtender{ + IA: topo.IA(), + SignerGen: tc.SignerGen, + MAC: func() hash.Hash { + mac, err := scrypto.InitMac(make([]byte, 16)) + require.NoError(t, err) + return mac + }, + Intfs: intfs, + MTU: 1337, + MaxExpTime: tc.MaxExpTime, + StaticInfo: func() *beaconing.StaticInfoCfg { return nil }, + } + pseg, err := seg.CreateSegment(ts, uint16(mrand.Int())) + require.NoError(t, err) + err = ext.Extend(context.Background(), pseg, 0, graph.If_111_A_112_X, []uint16{}) + tc.ErrAssertion(t, err) + if err != nil { + return + } + assert.Equal(t, tc.ExpTime, pseg.ASEntries[0].HopEntry.HopField.ExpTime) + }) + } + }) + t.Run("segment is not extended on error", func(t *testing.T) { defaultSigner := func(t *testing.T) seg.Signer { return testSigner(t, priv, topo.IA()) @@ -238,8 +338,8 @@ func TestDefaultExtenderExtend(t *testing.T) { defer mctrl.Finish() intfs := ifstate.NewInterfaces(interfaceInfos(topo), ifstate.Config{}) ext := &beaconing.DefaultExtender{ - IA: topo.IA(), - Signer: testSigner(t, priv, topo.IA()), + IA: topo.IA(), + SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())}, MAC: func() hash.Hash { mac, err := scrypto.InitMac(make([]byte, 16)) require.NoError(t, err) diff --git a/control/beaconing/originator_test.go b/control/beaconing/originator_test.go index 3c9d78d1f..8c15c57a1 100644 --- a/control/beaconing/originator_test.go +++ b/control/beaconing/originator_test.go @@ -69,7 +69,7 @@ func TestOriginatorRun(t *testing.T) { Extender: &beaconing.DefaultExtender{ IA: topo.IA(), MTU: topo.MTU(), - Signer: signer, + SignerGen: testSignerGen{Signer: signer}, Intfs: intfs, MAC: macFactory, MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime }, @@ -130,7 +130,7 @@ func TestOriginatorRun(t *testing.T) { Extender: &beaconing.DefaultExtender{ IA: topo.IA(), MTU: topo.MTU(), - Signer: signer, + SignerGen: testSignerGen{Signer: signer}, Intfs: intfs, MAC: macFactory, MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime }, diff --git a/control/beaconing/propagator_test.go b/control/beaconing/propagator_test.go index 1bd1ea99e..90bac1be6 100644 --- a/control/beaconing/propagator_test.go +++ b/control/beaconing/propagator_test.go @@ -64,7 +64,7 @@ func TestPropagatorRunNonCore(t *testing.T) { Extender: &beaconing.DefaultExtender{ IA: topo.IA(), MTU: topo.MTU(), - Signer: testSigner(t, priv, topo.IA()), + SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())}, Intfs: intfs, MAC: macFactory, MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime }, @@ -138,7 +138,7 @@ func TestPropagatorRunCore(t *testing.T) { Extender: &beaconing.DefaultExtender{ IA: topo.IA(), MTU: topo.MTU(), - Signer: testSigner(t, priv, topo.IA()), + SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())}, Intfs: intfs, MAC: macFactory, MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime }, @@ -226,7 +226,7 @@ func TestPropagatorFastRecovery(t *testing.T) { Extender: &beaconing.DefaultExtender{ IA: topo.IA(), MTU: topo.MTU(), - Signer: testSigner(t, priv, topo.IA()), + SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())}, Intfs: intfs, MAC: macFactory, MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime }, diff --git a/control/beaconing/writer_test.go b/control/beaconing/writer_test.go index 4613aa1e9..e253f6b2d 100644 --- a/control/beaconing/writer_test.go +++ b/control/beaconing/writer_test.go @@ -99,7 +99,7 @@ func TestRegistrarRun(t *testing.T) { Extender: &beaconing.DefaultExtender{ IA: topo.IA(), MTU: topo.MTU(), - Signer: testSigner(t, priv, topo.IA()), + SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())}, Intfs: intfs, MAC: macFactory, MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime }, @@ -185,7 +185,7 @@ func TestRegistrarRun(t *testing.T) { Extender: &beaconing.DefaultExtender{ IA: topo.IA(), MTU: topo.MTU(), - Signer: testSigner(t, priv, topo.IA()), + SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())}, Intfs: intfs, MAC: macFactory, MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime }, @@ -284,7 +284,7 @@ func TestRegistrarRun(t *testing.T) { Extender: &beaconing.DefaultExtender{ IA: topo.IA(), MTU: topo.MTU(), - Signer: testSigner(t, priv, topo.IA()), + SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())}, Intfs: intfs, MAC: macFactory, MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime }, @@ -330,7 +330,7 @@ func testBeacon(g *graph.Graph, desc []uint16) beacon.Beacon { } } -func testSigner(t *testing.T, priv crypto.Signer, ia addr.IA) seg.Signer { +func testSigner(t *testing.T, priv crypto.Signer, ia addr.IA) trust.Signer { return trust.Signer{ PrivateKey: priv, Algorithm: signed.ECDSAWithSHA256, @@ -345,6 +345,14 @@ func testSigner(t *testing.T, priv crypto.Signer, ia addr.IA) seg.Signer { } } +type testSignerGen struct { + Signer trust.Signer +} + +func (s testSignerGen) Generate(ctx context.Context) (trust.Signer, error) { + return s.Signer, nil +} + var macFactory = func() hash.Hash { mac, err := scrypto.InitMac(make([]byte, 16)) // This can only happen if the library is messed up badly. diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index 1b192cf13..8c01a43a3 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -776,7 +776,7 @@ func realMain(ctx context.Context) error { }, SegmentRegister: beaconinggrpc.Registrar{Dialer: dialer}, BeaconStore: beaconStore, - Signer: signer, + SignerGen: signer.SignerGen, Inspector: inspector, Metrics: metrics, DRKeyEngine: drkeyEngine, diff --git a/control/mgmtapi/testdata/TestAPI_beacon b/control/mgmtapi/testdata/TestAPI_beacon index 8f4c65c16..f47062d66 100644 --- a/control/mgmtapi/testdata/TestAPI_beacon +++ b/control/mgmtapi/testdata/TestAPI_beacon @@ -1,6 +1,6 @@ { "beacon": { - "expiration": "2021-01-01T08:05:37Z", + "expiration": "2021-01-01T08:05:37.5Z", "hops": [ { "interface": 1, diff --git a/control/mgmtapi/testdata/TestAPI_beacon_id_prefix b/control/mgmtapi/testdata/TestAPI_beacon_id_prefix index 8f4c65c16..f47062d66 100644 --- a/control/mgmtapi/testdata/TestAPI_beacon_id_prefix +++ b/control/mgmtapi/testdata/TestAPI_beacon_id_prefix @@ -1,6 +1,6 @@ { "beacon": { - "expiration": "2021-01-01T08:05:37Z", + "expiration": "2021-01-01T08:05:37.5Z", "hops": [ { "interface": 1, diff --git a/control/mgmtapi/testdata/TestAPI_beacons b/control/mgmtapi/testdata/TestAPI_beacons index ef36d2859..cc1ac3bf2 100644 --- a/control/mgmtapi/testdata/TestAPI_beacons +++ b/control/mgmtapi/testdata/TestAPI_beacons @@ -1,7 +1,7 @@ { "beacons": [ { - "expiration": "2021-01-01T08:05:37Z", + "expiration": "2021-01-01T08:05:37.5Z", "hops": [ { "interface": 1, @@ -26,7 +26,7 @@ ] }, { - "expiration": "2021-02-01T08:05:37Z", + "expiration": "2021-02-01T08:05:37.5Z", "hops": [ { "interface": 5, diff --git a/control/mgmtapi/testdata/TestAPI_beacons_descending_order b/control/mgmtapi/testdata/TestAPI_beacons_descending_order index d09cdf60f..71b3bfeec 100644 --- a/control/mgmtapi/testdata/TestAPI_beacons_descending_order +++ b/control/mgmtapi/testdata/TestAPI_beacons_descending_order @@ -1,7 +1,7 @@ { "beacons": [ { - "expiration": "2021-02-01T08:05:37Z", + "expiration": "2021-02-01T08:05:37.5Z", "hops": [ { "interface": 5, @@ -25,7 +25,7 @@ ] }, { - "expiration": "2021-01-01T08:05:37Z", + "expiration": "2021-01-01T08:05:37.5Z", "hops": [ { "interface": 1, diff --git a/control/mgmtapi/testdata/TestAPI_beacons_existing_usages b/control/mgmtapi/testdata/TestAPI_beacons_existing_usages index f32ef063b..081823fc2 100644 --- a/control/mgmtapi/testdata/TestAPI_beacons_existing_usages +++ b/control/mgmtapi/testdata/TestAPI_beacons_existing_usages @@ -1,7 +1,7 @@ { "beacons": [ { - "expiration": "2021-01-01T08:05:37Z", + "expiration": "2021-01-01T08:05:37.5Z", "hops": [ { "interface": 1, diff --git a/control/mgmtapi/testdata/TestAPI_beacons_sort_by_ingress_interface b/control/mgmtapi/testdata/TestAPI_beacons_sort_by_ingress_interface index d09cdf60f..71b3bfeec 100644 --- a/control/mgmtapi/testdata/TestAPI_beacons_sort_by_ingress_interface +++ b/control/mgmtapi/testdata/TestAPI_beacons_sort_by_ingress_interface @@ -1,7 +1,7 @@ { "beacons": [ { - "expiration": "2021-02-01T08:05:37Z", + "expiration": "2021-02-01T08:05:37.5Z", "hops": [ { "interface": 5, @@ -25,7 +25,7 @@ ] }, { - "expiration": "2021-01-01T08:05:37Z", + "expiration": "2021-01-01T08:05:37.5Z", "hops": [ { "interface": 1, diff --git a/control/observability.go b/control/observability.go index e8ef24095..371f3a056 100644 --- a/control/observability.go +++ b/control/observability.go @@ -73,6 +73,7 @@ type Metrics struct { SegmentLookupRequestsTotal *prometheus.CounterVec SegmentLookupSegmentsSentTotal *prometheus.CounterVec SegmentRegistrationsTotal *prometheus.CounterVec + SegmentExpirationDeficient *prometheus.GaugeVec TrustDBQueriesTotal *prometheus.CounterVec TrustLatestTRCNotBefore prometheus.Gauge TrustLatestTRCNotAfter prometheus.Gauge @@ -242,6 +243,15 @@ func NewMetrics() *Metrics { }, []string{"src", "seg_type", prom.LabelResult}, ), + SegmentExpirationDeficient: promauto.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "control_segment_expiration_deficient", + Help: "Indicates whether the expiration time of the segment is below the " + + "configured maximum. This happens when the signer expiration time is lower " + + "than the maximum segment expiration time.", + }, + []string{}, + ), TrustDBQueriesTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "trustengine_db_queries_total", diff --git a/control/tasks.go b/control/tasks.go index fedae5e90..4de2588cc 100644 --- a/control/tasks.go +++ b/control/tasks.go @@ -56,7 +56,7 @@ type TasksConfig struct { BeaconSenderFactory beaconing.SenderFactory SegmentRegister beaconing.RPC BeaconStore Store - Signer seg.Signer + SignerGen beaconing.SignerGen Inspector trust.Inspector Metrics *Metrics DRKeyEngine *drkey.ServiceEngine @@ -92,7 +92,6 @@ func (t *TasksConfig) Originator() *periodic.Runner { IA: t.IA, AllInterfaces: t.AllInterfaces, OriginationInterfaces: t.OriginationInterfaces, - Signer: t.Signer, Tick: beaconing.NewTick(t.OriginationInterval), } if t.Metrics != nil { @@ -110,7 +109,6 @@ func (t *TasksConfig) Propagator() *periodic.Runner { SenderFactory: t.BeaconSenderFactory, Provider: t.BeaconStore, IA: t.IA, - Signer: t.Signer, AllInterfaces: t.AllInterfaces, PropagationInterfaces: t.PropagationInterfaces, AllowIsdLoop: t.AllowIsdLoop, @@ -204,12 +202,16 @@ func (t *TasksConfig) segmentWriter(segType seg.Type, return periodic.Start(r, 500*time.Millisecond, t.RegistrationInterval) } -func (t *TasksConfig) extender(task string, ia addr.IA, mtu uint16, - maxExp func() uint8) beaconing.Extender { +func (t *TasksConfig) extender( + task string, + ia addr.IA, + mtu uint16, + maxExp func() uint8, +) beaconing.Extender { return &beaconing.DefaultExtender{ IA: ia, - Signer: t.Signer, + SignerGen: t.SignerGen, MAC: t.MACGen, Intfs: t.AllInterfaces, MTU: mtu, @@ -217,6 +219,12 @@ func (t *TasksConfig) extender(task string, ia addr.IA, mtu uint16, StaticInfo: t.StaticInfo, Task: task, EPIC: t.EPIC, + SegmentExpirationDeficient: func() metrics.Gauge { + if t.Metrics == nil { + return nil + } + return metrics.NewPromGauge(t.Metrics.SegmentExpirationDeficient) + }(), } } diff --git a/pkg/experimental/hiddenpath/beaconwriter_test.go b/pkg/experimental/hiddenpath/beaconwriter_test.go index 3cd383fa2..b9b0cabcc 100644 --- a/pkg/experimental/hiddenpath/beaconwriter_test.go +++ b/pkg/experimental/hiddenpath/beaconwriter_test.go @@ -196,7 +196,7 @@ func TestRemoteBeaconWriterWrite(t *testing.T) { Extender: &beaconing.DefaultExtender{ IA: topo.IA(), MTU: topo.MTU(), - Signer: testSigner(t, priv, topo.IA()), + SignerGen: testSignerGen{Signer: testSigner(t, priv, topo.IA())}, Intfs: intfs, MAC: macFactory, MaxExpTime: func() uint8 { return beacon.DefaultMaxExpTime }, @@ -236,7 +236,7 @@ func testBeacon(g *graph.Graph, desc []uint16) beacon.Beacon { } } -func testSigner(t *testing.T, priv crypto.Signer, ia addr.IA) seg.Signer { +func testSigner(t *testing.T, priv crypto.Signer, ia addr.IA) trust.Signer { return trust.Signer{ PrivateKey: priv, Algorithm: signed.ECDSAWithSHA256, @@ -352,6 +352,14 @@ func (w topoWrap) UnderlayNextHop(id uint16) *net.UDPAddr { return a } +type testSignerGen struct { + Signer trust.Signer +} + +func (s testSignerGen) Generate(ctx context.Context) (trust.Signer, error) { + return s.Signer, nil +} + func interfaceInfos(topo topology.Topology) map[uint16]ifstate.InterfaceInfo { in := topo.IFInfoMap() result := make(map[uint16]ifstate.InterfaceInfo, len(in)) diff --git a/pkg/segment/seg.go b/pkg/segment/seg.go index ecc0467bf..a873b55b6 100644 --- a/pkg/segment/seg.go +++ b/pkg/segment/seg.go @@ -220,7 +220,7 @@ func (ps *PathSegment) MaxExpiry() time.Time { // MinExpiry returns the minimum expiry of all hop fields. // Assumes segment is validated. func (ps *PathSegment) MinExpiry() time.Time { - return ps.expiry(path.MaxTTL*time.Second, func(hfTtl time.Duration, ttl time.Duration) bool { + return ps.expiry(path.MaxTTL, func(hfTtl time.Duration, ttl time.Duration) bool { return hfTtl < ttl }) } diff --git a/pkg/slayers/path/hopfield.go b/pkg/slayers/path/hopfield.go index 0cb6b4870..c4415ce67 100644 --- a/pkg/slayers/path/hopfield.go +++ b/pkg/slayers/path/hopfield.go @@ -30,10 +30,10 @@ const ( MacLen = 6 ) -// MaxTTL is the maximum age of a HopField in seconds. -const MaxTTL = 24 * 60 * 60 // One day in seconds +// MaxTTL is the maximum age of a HopField. +const MaxTTL = 24 * time.Hour -const expTimeUnit = MaxTTL / 256 // ~5m38s +const expTimeUnit = MaxTTL / 256 // ~5m38.5s // HopField is the HopField used in the SCION and OneHop path types. // @@ -142,5 +142,20 @@ func (h *HopField) SerializeTo(b []byte) (err error) { // Calls to ExpTimeToDuration are guaranteed to always terminate. // @ decreases func ExpTimeToDuration(expTime uint8) time.Duration { - return (time.Duration(expTime) + 1) * time.Duration(expTimeUnit) * time.Second + return (time.Duration(expTime) + 1) * expTimeUnit +} + +// ExpTimeFromDuration calculates the largest relative expiration time that +// represents a duration <= the provided duration, that is: +// d <= ExpTimeToDuration(ExpTimeFromDuration(d)). +// The returned value is the ExpTime that can be used in a HopField. +// For durations that are out of range, an error is returned. +func ExpTimeFromDuration(d time.Duration) (uint8, error) { + if d < expTimeUnit { + return 0, serrors.New("duration too small", "seconds", d) + } + if d > MaxTTL { + return 0, serrors.New("duration too large", "seconds", d) + } + return uint8((d*256)/MaxTTL - 1), nil } diff --git a/pkg/slayers/path/hopfield_test.go b/pkg/slayers/path/hopfield_test.go index 4a7cfd8ad..c8f9ec803 100644 --- a/pkg/slayers/path/hopfield_test.go +++ b/pkg/slayers/path/hopfield_test.go @@ -16,6 +16,7 @@ package path_test import ( "testing" + "time" "github.com/stretchr/testify/assert" @@ -38,3 +39,49 @@ func TestHopSerializeDecode(t *testing.T) { assert.NoError(t, got.DecodeFromBytes(b)) assert.Equal(t, want, got) } + +func TestExpTimeFromDuration(t *testing.T) { + tests := map[string]struct { + d time.Duration + ExpTime uint8 + ErrorF assert.ErrorAssertionFunc + }{ + "Zero": { + d: 0, + ExpTime: 0, + ErrorF: assert.Error, + }, + "Max": { + d: path.MaxTTL, + ExpTime: 255, + ErrorF: assert.NoError, + }, + "Overflow": { + d: (path.MaxTTL + 1), + ExpTime: 0, + ErrorF: assert.Error, + }, + "Underflow": { + d: -1, + ExpTime: 0, + ErrorF: assert.Error, + }, + "Max-1": { + d: (path.MaxTTL - 1), + ExpTime: 254, + ErrorF: assert.NoError, + }, + "Half": { + d: (path.MaxTTL / 2), + ExpTime: 127, + ErrorF: assert.NoError, + }, + } + for name, test := range tests { + t.Run(name, func(t *testing.T) { + expTime, err := path.ExpTimeFromDuration(test.d) + test.ErrorF(t, err) + assert.Equal(t, test.ExpTime, expTime) + }) + } +} diff --git a/private/app/appnet/intra_as.go b/private/app/appnet/intra_as.go index 6735dce53..743ac9631 100644 --- a/private/app/appnet/intra_as.go +++ b/private/app/appnet/intra_as.go @@ -42,7 +42,7 @@ func (q IntraASPathQuerier) Query(_ context.Context, _ addr.IA) ([]snet.Path, er DataplanePath: path.Empty{}, Meta: snet.PathMetadata{ MTU: q.MTU, - Expiry: time.Now().Add(rawpath.MaxTTL * time.Second), + Expiry: time.Now().Add(rawpath.MaxTTL), }, }}, nil } diff --git a/private/mgmtapi/segments/api/testdata/segments-by-id.json b/private/mgmtapi/segments/api/testdata/segments-by-id.json index 1efc22952..5ecdc2864 100644 --- a/private/mgmtapi/segments/api/testdata/segments-by-id.json +++ b/private/mgmtapi/segments/api/testdata/segments-by-id.json @@ -1,5 +1,5 @@ { - "expiration": "2021-01-19T10:17:38Z", + "expiration": "2021-01-19T10:17:38.5Z", "hops": [ { "interface": 1, diff --git a/private/path/combinator/expiry_test.go b/private/path/combinator/expiry_test.go index e87b71c9d..6d8e86bbf 100644 --- a/private/path/combinator/expiry_test.go +++ b/private/path/combinator/expiry_test.go @@ -39,7 +39,7 @@ func TestComputeSegmentExpTime(t *testing.T) { { Name: "non-zero hop ttl field value", Segment: buildTestSegment(0, 1), - ExpectedExpiration: 674, + ExpectedExpiration: 675, }, { Name: "two hop fields, min should be taken", @@ -49,29 +49,29 @@ func TestComputeSegmentExpTime(t *testing.T) { { Name: "maximum ttl selected", Segment: buildTestSegment(0, 255), - ExpectedExpiration: 24*60*60 - 128, // rounding error drift + ExpectedExpiration: 24 * 60 * 60, }, { Name: "ttl relative to info field timestamp", Segment: buildTestSegment(100, 1), - ExpectedExpiration: 774, + ExpectedExpiration: 775, }, { Name: "ttl relative to maximum info field timestamp", Segment: buildTestSegment(4294967295, 1), - ExpectedExpiration: 4294967969, + ExpectedExpiration: 4294967970, }, { Name: "maximum possible value", Segment: buildTestSegment(4294967295, 255), - ExpectedExpiration: 4295053695 - 128, // rounding error drift + ExpectedExpiration: 4295053695, }, } t.Log("Expiration values should be correct") for _, tc := range testCases { t.Run(tc.Name, func(t *testing.T) { computedExpiration := tc.Segment.ComputeExpTime() - assert.Equal(t, computedExpiration.Unix(), tc.ExpectedExpiration) + assert.Equal(t, tc.ExpectedExpiration, computedExpiration.Unix()) }) } diff --git a/private/path/combinator/graph.go b/private/path/combinator/graph.go index eb092ca70..cfb1e7160 100644 --- a/private/path/combinator/graph.go +++ b/private/path/combinator/graph.go @@ -627,7 +627,7 @@ func (segment *segment) ComputeExpTime() time.Time { } func (segment *segment) computeHopFieldsTTL() time.Duration { - minTTL := time.Duration(path.MaxTTL) * time.Second + minTTL := path.MaxTTL for _, hf := range segment.HopFields { offset := path.ExpTimeToDuration(hf.ExpTime) if minTTL > offset { diff --git a/private/segment/segfetcher/pather.go b/private/segment/segfetcher/pather.go index 68b39962d..f168cc6ac 100644 --- a/private/segment/segfetcher/pather.go +++ b/private/segment/segfetcher/pather.go @@ -70,7 +70,7 @@ func (p *Pather) GetPaths(ctx context.Context, dst addr.IA, Dst: dst, Meta: snet.PathMetadata{ MTU: p.MTU, - Expiry: time.Now().Add(rawpath.MaxTTL * time.Second), + Expiry: time.Now().Add(rawpath.MaxTTL), }, }}, nil } From 2ea2d8913ef2b85a23cbad42b14b74c2c698c1c6 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 12 Oct 2023 13:40:46 +0200 Subject: [PATCH 068/255] doc: touch up manuals, enable fail-on-warning for docs (#4416) - add missing documentation for `remote_interface_id` in `topology.json` for peering links (fix-up for #4390) - fix duplicate envvar documentation in router.rst and control.rst (envvars can only have one definition in rst), and expand the description (fix-up for #4300). Consistent formatting for envvar documentation. - move the description of the duration string format to the common section, as it's referenced by multiple components (currently control service and router). - fix references in SPAO doc - enable fail-on-warning for read-the-docs builds: this makes PR fail the the read-the-docs check if there are build warnings. Also enable the same build flags in the Makefile for local documentation builds. --- .readthedocs.yaml | 1 + doc/Makefile | 5 +-- doc/control-plane.rst | 2 ++ doc/manuals/common.rst | 48 ++++++++++++++++++++++++-- doc/manuals/control.rst | 33 ++++-------------- doc/manuals/router.rst | 45 ++++++++++++++++++------ doc/protocols/authenticator-option.rst | 2 +- 7 files changed, 94 insertions(+), 42 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 973c7d33b..cfcdbd001 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -11,6 +11,7 @@ build: sphinx: configuration: doc/conf.py + fail_on_warning: true python: install: diff --git a/doc/Makefile b/doc/Makefile index fc16ae624..719138594 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,5 +1,5 @@ # These variables can be overridden from the command line from the environment. -SPHINXOPTS ?= +SPHINXOPTS ?= -W --keep-going # treat warnings as errors, but process all files when an error occurs SOURCEDIR = . BUILDDIR = _build @@ -16,9 +16,10 @@ html latex latexpdf linkcheck help: sphinx-build -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) # Autobuild; automatically build HTML on source changes and serve on localhost +# Note: most options are forwarded as-is to sphinx, but --keep-going is not understood and we explicitly drop it. .PHONY: autobuild autobuild: - sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) + sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(filter-out --keep-going,$(SPHINXOPTS)) # Generate commandline docs by building the tools and running their `gendocus` subcommand .PHONY: command-gendocs diff --git a/doc/control-plane.rst b/doc/control-plane.rst index eca9ce072..edca6c4fb 100644 --- a/doc/control-plane.rst +++ b/doc/control-plane.rst @@ -266,6 +266,8 @@ path-lookup on behalf of applications. This SCION daemon also caches path-segmen Down-segment Control service of core ASes in destination ISD (either the local ISD or a remote ISD) ============ =========================== +.. _control-plane-segment-combination: + Path-Segment Combination ======================== diff --git a/doc/manuals/common.rst b/doc/manuals/common.rst index 6bc3e4b21..863c58b15 100644 --- a/doc/manuals/common.rst +++ b/doc/manuals/common.rst @@ -202,6 +202,8 @@ of the individual fields below. In this ``topology.json`` file, the ID is contained in a string. + .. _topology-json-interface-isd_as: + .. option:: isd_as = , required The ISD-AS of the neighboring AS. @@ -211,16 +213,34 @@ of the individual fields below. Type of the link relation to the neighbor AS. See :ref:`overview-link-types`. - .. warning:: + .. option:: remote_interface_id = + + The :term:`interface ID ` for the corresponding interface in the + neighboring AS. + + This is required if, and only if, :option:`link_to ` is ``peer``. + + This ``remote_interface_id`` is used when announcing peering links as part of AS Entries in + PCBs (see :ref:`control-plane-beaconing`). + During :ref:`path-segment combination `, this interface + ID, will then be used together with the ISD-AS to match up the peering entries from + AS entries in different path segments. - Link type ``peer`` is not fully implemented yet. See :issue:`4093`. + If ``remote_interface_id`` is set incorrectly, the peering entries cannot be matched up + correctly, resulting in missing or broken end-to-end paths: + + - If the ``remote_interface_id`` does not match `any` interface ID used for peering links + in the neighboring AS, the segment combination will not find paths making use of this + interface. + - If two ASes are connected by multiple peering links and ``remote_interface_id`` matches the + `wrong` interface ID, an incorrect path may be constructed which will be rejected in the + data plane (i.e. the routers will drop all packets). .. option:: mtu = , required Maximum Transmission Unit in bytes for SCION packets (SCION headers and payload) on this link. - .. object:: underlay, required for "self" Underlay specifies the local addresses used for the underlay IP/UDP connection to the @@ -325,6 +345,28 @@ of the individual fields below. .. option:: addr = , required See ``control_service.addr``, above. + +.. _common-conf-duration: + +Duration Format +=============== + +Where duration values are loaded from configuration options, the following format is expected: + +.. code-block:: + + [\-0-9]+(y|w|d|h|m|s|ms|us|µs|ns) + +The unit suffixes have their usual meaning of ``y`` year, ``w`` week, ``d`` day, ``h`` hour, +``m`` minute, ``s`` second, ``ms`` millisecond, ``us`` or ``µs`` microsecond, and ``ns`` nanosecond. + +Mixed unit durations are not supported (e.g. ``1h10m10s`` is not supported). +The long duration units are simple factors, not calendar offsets: + +- ``d`` is always 24 hours +- ``w`` is always 7 days +- ``y`` is always 365 days + .. _common-http-api: HTTP API diff --git a/doc/manuals/control.rst b/doc/manuals/control.rst index 0bcbe8017..310a3bdcc 100644 --- a/doc/manuals/control.rst +++ b/doc/manuals/control.rst @@ -64,6 +64,7 @@ Options Run :option:`control help completion [shell] ` for usage information on the autocomplete script for a particular shell. +.. _control-envvars: Environment variables --------------------- @@ -76,7 +77,10 @@ Environment variables This can only work correctly if the same value is set for all connected control services in the test network. - The format is a :ref:`duration ` with unit suffix (e.g. ``10s``). + Also applies to the :ref:`router `. + + :Type: :ref:`duration ` + :Default: ``24h`` Configuration ============= @@ -264,7 +268,7 @@ considers the following options. .. option:: ca.service.lifetime = (Default: "10m") - Validity period (a :ref:`duration `) of JWT authorization tokens + Validity period (a :ref:`duration `) of JWT authorization tokens for the CA service. .. option:: ca.service.client_id = (Default: general.id) @@ -315,7 +319,7 @@ considers the following options. Expiration of cached entries in nanoseconds. - **TODO:** this should be changed to accept values in :ref:`duration format `. + **TODO:** this should be changed to accept values in :ref:`duration format `. .. object:: drkey @@ -775,29 +779,6 @@ There is one top-level entry for each type of metadata, all of which are optiona A free form string to communicate interesting/important information to other network operators. - -.. _control-conf-duration: - -Duration Format ---------------- - -Where duration values are loaded from configuration options, the following format is expected: - -.. code-block:: - - [\-0-9]+(y|w|d|h|m|s|ms|us|µs|ns) - -The unit suffixes have their usual meaning of ``y`` year, ``w`` week, ``d`` day, ``h`` hour, -``m`` minute, ``s`` second, ``ms`` millisecond, ``us`` or ``µs`` microsecond, and ``ns`` nanosecond. - -Mixed unit durations are not supported (e.g. ``1h10m10s`` is not supported). -The long duration units are simple factors, not calendar offsets: - -- ``d`` is always 24 hours -- ``w`` is always 7 days -- ``y`` is always 365 days - - Port table ========== diff --git a/doc/manuals/router.rst b/doc/manuals/router.rst index 6427ab616..494012ec5 100644 --- a/doc/manuals/router.rst +++ b/doc/manuals/router.rst @@ -51,6 +51,8 @@ Options Run :option:`router help completion [shell] ` for usage information on the autocomplete script for a particular shell. +.. _router-envvars: + Environment Variables --------------------- @@ -62,40 +64,63 @@ Environment Variables Can be overridden for specific inter-AS BFD sessions with :option:`bfd.disable ` in an interface entry in the ``topology.json`` configuration. + :Type: bool (``0``/``f``/``F``/``FALSE``/``false``/``False``, ``1``/``t``/``T``/``TRUE``/``true``/``True``) + :Default: ``false`` + .. envvar:: SCION_EXPERIMENTAL_BFD_DETECT_MULT Set the :term:`BFD` detection time multiplier. - Default 3 - Same applicability as above; can be overridden for specific inter-AS BFD sessions with :option:`bfd.detect_mult `. + :Type: unsigned integer + :Default: ``3`` + .. envvar:: SCION_EXPERIMENTAL_BFD_DESIRED_MIN_TX Defines the frequence at which this router should send :term:`BFD` control messages. - Default 200ms - Same applicability as above; can be overridden for specific inter-AS BFD sessions with :option:`bfd.desired_min_tx_interval `. + :Type: :ref:`duration ` + :Default: ``200ms`` + .. envvar:: SCION_EXPERIMENTAL_BFD_REQUIRED_MIN_RX Defines an frequence at which this router should send :term:`BFD` control messages. - Default 200ms - Same applicability as above; can be overridden for specific inter-AS BFD sessions with :option:`bfd.required_min_rx_interval `. -.. envvar:: SCION_TESTING_DRKEY_EPOCH_DURATION - Defines the global DRKey :ref:`Epoch` duration that the border router - assumes. + :Type: :ref:`duration ` + :Default: ``200ms`` + +.. object:: SCION_TESTING_DRKEY_EPOCH_DURATION + + For **testing only**. + This option relates to :ref:`DRKey-based authentication of SCMPs ` in the + router, which is **experimental** and currently **incomplete**. + + Override the global duration for :doc:`/cryptography/drkey` epochs. + + Also applies to the :ref:`control service `. + + :Type: :ref:`duration ` + :Default: ``24h`` .. envvar:: SCION_TESTING_ACCEPTANCE_WINDOW - Defines the acceptance window following the :ref:`SPAO specification`. + For **testing only**. + This option relates to :ref:`DRKey-based authentication of SCMPs ` in the + router, which is **experimental** and currently **incomplete**. + + Defines the length of the window around the current time for which SCMP authentication timestamps + are accepted. See :ref:`SPAO specification `. + + :Type: :ref:`duration ` + :Default: ``5m`` Configuration ============= diff --git a/doc/protocols/authenticator-option.rst b/doc/protocols/authenticator-option.rst index 077069603..a8ecca2ef 100644 --- a/doc/protocols/authenticator-option.rst +++ b/doc/protocols/authenticator-option.rst @@ -60,7 +60,7 @@ Timestamp / Sequence Number: (See :ref:`Appendix` for a more detailed explanation about the field interpretation). The timestamp MAY be used to compute the absolute time (*AbsTime*) value, which corresponds to the time when the packet was sent. - The section :ref:`Absolute time derivation` describes the derivation of *AbsTime* and + The section :ref:`Absolute time derivation` describes the derivation of *AbsTime* and the associated DRKey. The receiver SHOULD drop packets with *AbsTime* outside of a locally chosen From 44c2f6766c74bc6e4df797952b68128004fba574 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 12 Oct 2023 14:39:07 +0200 Subject: [PATCH 069/255] router: feature toggle for experimental SCMP authentication (#4418) The experimental implementation of DRKey-based authentication for SCMP messages is incomplete and, in the current form, not practically useful. Add a feature flag to explicitly opt-in to the experimental SCMP authentication in the router. --- acceptance/router_multi/conf/br.toml | 3 +++ doc/manuals/router.rst | 19 +++++++++++++++---- private/env/features.go | 9 +++++++++ router/cmd/router/main.go | 3 ++- router/dataplane.go | 21 +++++++++++++-------- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/acceptance/router_multi/conf/br.toml b/acceptance/router_multi/conf/br.toml index 8c997390e..5fa757f1c 100644 --- a/acceptance/router_multi/conf/br.toml +++ b/acceptance/router_multi/conf/br.toml @@ -2,6 +2,9 @@ id = "brA" config_dir = "/share/conf" +[features] + experimental_scmp_authentication = true + [log] [log.console] level = "debug" diff --git a/doc/manuals/router.rst b/doc/manuals/router.rst index 494012ec5..c68768754 100644 --- a/doc/manuals/router.rst +++ b/doc/manuals/router.rst @@ -100,8 +100,7 @@ Environment Variables .. object:: SCION_TESTING_DRKEY_EPOCH_DURATION For **testing only**. - This option relates to :ref:`DRKey-based authentication of SCMPs ` in the - router, which is **experimental** and currently **incomplete**. + This option relates :option:`features.experimental_scmp_authentication `. Override the global duration for :doc:`/cryptography/drkey` epochs. @@ -113,8 +112,7 @@ Environment Variables .. envvar:: SCION_TESTING_ACCEPTANCE_WINDOW For **testing only**. - This option relates to :ref:`DRKey-based authentication of SCMPs ` in the - router, which is **experimental** and currently **incomplete**. + This option relates :option:`features.experimental_scmp_authentication `. Defines the length of the window around the current time for which SCMP authentication timestamps are accepted. See :ref:`SPAO specification `. @@ -158,6 +156,19 @@ considers the following options. If this is a relative path, it is interpreted as relative to the current working directory of the program (i.e. **not** relative to the location of this .toml configuration file). +.. object:: features + + Features is a container for generic, boolean feature flags (usually for experimental or + transitional features). + + .. option:: features.experimental_scmp_authentication = (Default: false) + + Enable the :ref:`DRKey-based authentication of SCMPs ` in the + router, which is **experimental** and currently **incomplete**. + + When enabled, the router inserts the :ref:`authenticator-option` for SCMP messages. + For now, the MAC is computed based on a dummy key, and consequently is not practically useful. + .. object:: router .. option:: router.receive_buffer_size = (Default: 0) diff --git a/private/env/features.go b/private/env/features.go index cd62fced8..c004ec21d 100644 --- a/private/env/features.go +++ b/private/env/features.go @@ -36,6 +36,15 @@ type Features struct { // Example: // DanceAtMidnight bool `toml:"dance_at_midnight,omitempty"` + + // ExperimentalSCMPAuthentication enables experimental, DRKey-based + // authentication of SCMP messages. + // + // When enabled, the router inserts the SPAO authenticator for SCMP error messages, + // generated with a dummy key! + // + // Experimental: This field is experimental and will be subject to change. + ExperimentalSCMPAuthentication bool `toml:"experimental_scmp_authentication"` } func (cfg *Features) Sample(dst io.Writer, path config.Path, ctx config.CtxMap) { diff --git a/router/cmd/router/main.go b/router/cmd/router/main.go index c2ecdbdbf..f458ab254 100644 --- a/router/cmd/router/main.go +++ b/router/cmd/router/main.go @@ -58,7 +58,8 @@ func realMain(ctx context.Context) error { metrics := router.NewMetrics() dp := &router.Connector{ DataPlane: router.DataPlane{ - Metrics: metrics, + Metrics: metrics, + ExperimentalSCMPAuthentication: globalCfg.Features.ExperimentalSCMPAuthentication, }, ReceiveBufferSize: globalCfg.Router.ReceiveBufferSize, SendBufferSize: globalCfg.Router.SendBufferSize, diff --git a/router/dataplane.go b/router/dataplane.go index 57b533da4..362c298c3 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -112,6 +112,8 @@ type DataPlane struct { Metrics *Metrics forwardingMetrics map[uint16]forwardingMetrics + ExperimentalSCMPAuthentication bool + // The pool that stores all the packet buffers as described in the design document. See // https://github.com/scionproto/scion/blob/master/doc/dev/design/BorderRouter.rst packetPool chan []byte @@ -2153,14 +2155,17 @@ func (p *slowPathPacketProcessor) prepareSCMP( scmpH := slayers.SCMP{TypeCode: typeCode} scmpH.SetNetworkLayerForChecksum(&scionL) - // Error messages must be authenticated. - // Traceroute are OPTIONALLY authenticated ONLY IF the request - // was authenticated. - // TODO(JordiSubira): Reuse the key computed in p.hasValidAuth - // if SCMPTypeTracerouteReply to create the response. - needsAuth := cause != nil || - (scmpH.TypeCode.Type() == slayers.SCMPTypeTracerouteReply && - p.hasValidAuth(time.Now())) + needsAuth := false + if p.d.ExperimentalSCMPAuthentication { + // Error messages must be authenticated. + // Traceroute are OPTIONALLY authenticated ONLY IF the request + // was authenticated. + // TODO(JordiSubira): Reuse the key computed in p.hasValidAuth + // if SCMPTypeTracerouteReply to create the response. + needsAuth = cause != nil || + (scmpH.TypeCode.Type() == slayers.SCMPTypeTracerouteReply && + p.hasValidAuth(time.Now())) + } var quote []byte if cause != nil { From 1a51838369b7536c08da2a655e747ba2d0a721eb Mon Sep 17 00:00:00 2001 From: Edoardo Ottavianelli Date: Thu, 12 Oct 2023 14:47:47 +0200 Subject: [PATCH 070/255] doc: fix typos (#4421) Fix misc typos in docs. --- doc/control-plane.rst | 6 +++--- doc/glossary.rst | 2 +- doc/hidden-paths.rst | 2 +- doc/protocols/authenticator-option.rst | 2 +- doc/protocols/extension-header.rst | 2 +- doc/protocols/scion-header.rst | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/control-plane.rst b/doc/control-plane.rst index edca6c4fb..62731987b 100644 --- a/doc/control-plane.rst +++ b/doc/control-plane.rst @@ -106,7 +106,7 @@ An originated PCB sent to a child AS initiates the intra-ISD beacon creating an Propagation of PCBs ------------------- -PCBs are propgated at regular intervals at each AS. +PCBs are propagated at regular intervals at each AS. When PCBs are received, they are not propagated immediately, but put into temporary storage until the next propagation event. The selection and propagation of PCBs differs between the inter-ISD and intra-ISD beacon schemes. @@ -160,7 +160,7 @@ or :file-ref:`proto/control_plane/v1/seg.proto` for the raw protocol definitions :end-at: } .. literalinclude:: /../proto/control_plane/v1/seg.proto - :caption: Hop field protobuf message definition. This is a part of the ``HopEntry``, refererred to + :caption: Hop field protobuf message definition. This is a part of the ``HopEntry``, referred to in the ``ASEntrySignedBody`` definition above. :language: proto :start-at: message HopField { @@ -188,7 +188,7 @@ lookup process. As mentioned previously, a non-core AS typically receives several PCBs representing path segments to the core ASes of the ISD the AS belongs to. Out of these PCBs, the non-core AS selects those down-path segments through which it wants to be -reached, based on AS-specific selection critera. +reached, based on AS-specific selection criteria. The next step is to register the selected down-segments with the control service of the core AS that originated the PCB. diff --git a/doc/glossary.rst b/doc/glossary.rst index 0083dcdbc..68810d69a 100644 --- a/doc/glossary.rst +++ b/doc/glossary.rst @@ -53,7 +53,7 @@ Glossary An endpoint can be an end host, but it applies slightly more generically to any node which is the source or destination of SCION traffic, e.g. to a gateway. - The terms "endpoint" and "end host" are used mostly interchangably. + The terms "endpoint" and "end host" are used mostly interchangeably. End host is preferred where the focus is (physical or virtual) machines and the software running on them, and endpoint is used otherwise. diff --git a/doc/hidden-paths.rst b/doc/hidden-paths.rst index 4a24fd1aa..79f9fcd95 100644 --- a/doc/hidden-paths.rst +++ b/doc/hidden-paths.rst @@ -149,7 +149,7 @@ Below is an example registration configuration. Segments constructed via interfaces not listed in the registration policy will not be registered at all. This default prevents the scenario where an AS that wants to stay -hidden adds an new interface, and announces paths to itself without realizing. +hidden adds a new interface, and announces paths to itself without realizing. Example complete configuration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/protocols/authenticator-option.rst b/doc/protocols/authenticator-option.rst index a8ecca2ef..bf3d5811a 100644 --- a/doc/protocols/authenticator-option.rst +++ b/doc/protocols/authenticator-option.rst @@ -76,7 +76,7 @@ Timestamp / Sequence Number: .. note:: In other words, the duplicate suppression would happen within the acceptance windows considering identical values for the Authenticator field, which is - computed based on packet contents, such as the Timestamp (used to derived the *AbsTime*) + computed based on packet contents, such as the Timestamp (used to derive the *AbsTime*) and the upper layer payload (see the section :ref:`Authenticated Data`). diff --git a/doc/protocols/extension-header.rst b/doc/protocols/extension-header.rst index 23e1447e4..a93ce7559 100644 --- a/doc/protocols/extension-header.rst +++ b/doc/protocols/extension-header.rst @@ -8,7 +8,7 @@ This document contains the specification of the SCION extension headers. There are two extension headers defined, the *Hop-by-Hop (HBH) Options Header* and the *End-to-End (E2E) Options Header*. A SCION packet can have at most **one** of each. If both headers are present, the HBH options **MUST** come before the E2E -options. The option header support a variable number of *type-length-value +options. The option header supports a variable number of *type-length-value (TLV)* encoded options. .. _hop-by-hop-options: diff --git a/doc/protocols/scion-header.rst b/doc/protocols/scion-header.rst index db71176cc..c69093f96 100644 --- a/doc/protocols/scion-header.rst +++ b/doc/protocols/scion-header.rst @@ -173,7 +173,7 @@ current and preceding info fields. This construction allows for up to three info fields, which is the maximum for a SCION path. Should there ever be a path type with more than three segments, this would require a new path type to be introduced (which would also allow for a -backwards-compatible upgrade). The advantage of this construction is that all +backward-compatible upgrade). The advantage of this construction is that all the offsets can be calculated and validated purely from the path meta header, which greatly simplifies processing logic. @@ -203,7 +203,7 @@ C RSV Unused and reserved for future use. SegID - SegID is a updatable field that is required for the MAC-chaining mechanism. + SegID is an updatable field that is required for the MAC-chaining mechanism. Timestamp Timestamp created by the initiator of the corresponding beacon. The timestamp is expressed in Unix time, and is encoded as an unsigned integer From 46b055afc1ccbf3f604690bdc2e34758920d670e Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Mon, 16 Oct 2023 11:31:52 +0200 Subject: [PATCH 071/255] control: formatted duration for config trustengine.cache.expiration (#4417) The `trustengine.cache.expiration` configuration option would accept durations as number of nanoseconds. Most likely, this was accidental, all other configuration options for durations accept formatted duration strings, with unit suffix. Change `trustengine.cache.expiration` to accept (only) formatted duration strings. This is a potentially compatibility breaking change for existing control service and daemon configuration files. The `trustengine.cache` configuration block is marked as experimental and is likely not widely used, so no transition mechanism is added. --- control/cmd/control/main.go | 4 ++-- daemon/cmd/daemon/main.go | 4 ++-- doc/manuals/control.rst | 6 ++---- private/trust/config/BUILD.bazel | 1 + private/trust/config/config.go | 11 ++++++----- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index 8c01a43a3..0be35b0b5 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -271,7 +271,7 @@ func realMain(ctx context.Context) error { DB: trustDB, }, CacheHits: cacheHits, - MaxCacheExpiration: globalCfg.TrustEngine.Cache.Expiration, + MaxCacheExpiration: globalCfg.TrustEngine.Cache.Expiration.Duration, Cache: trustengineCache, } provider := trust.FetchingProvider{ @@ -288,7 +288,7 @@ func realMain(ctx context.Context) error { Verifier: trust.Verifier{ Engine: provider, CacheHits: cacheHits, - MaxCacheExpiration: globalCfg.TrustEngine.Cache.Expiration, + MaxCacheExpiration: globalCfg.TrustEngine.Cache.Expiration.Duration, Cache: trustengineCache, }, } diff --git a/daemon/cmd/daemon/main.go b/daemon/cmd/daemon/main.go index a8ec8ca52..ded6ef110 100644 --- a/daemon/cmd/daemon/main.go +++ b/daemon/cmd/daemon/main.go @@ -156,7 +156,7 @@ func realMain(ctx context.Context) error { Inspector: engine.Inspector, Cache: globalCfg.TrustEngine.Cache.New(), CacheHits: metrics.NewPromCounter(trustmetrics.CacheHitsTotal), - MaxCacheExpiration: globalCfg.TrustEngine.Cache.Expiration, + MaxCacheExpiration: globalCfg.TrustEngine.Cache.Expiration.Duration, } trcLoader := periodic.Start(periodic.Func{ Task: func(ctx context.Context) { @@ -247,7 +247,7 @@ func realMain(ctx context.Context) error { Engine: engine, Cache: globalCfg.TrustEngine.Cache.New(), CacheHits: metrics.NewPromCounter(trustmetrics.CacheHitsTotal), - MaxCacheExpiration: globalCfg.TrustEngine.Cache.Expiration, + MaxCacheExpiration: globalCfg.TrustEngine.Cache.Expiration.Duration, }} } diff --git a/doc/manuals/control.rst b/doc/manuals/control.rst index 310a3bdcc..5855abfd1 100644 --- a/doc/manuals/control.rst +++ b/doc/manuals/control.rst @@ -315,11 +315,9 @@ considers the following options. Disable caching entirely. - .. option:: trustengine.cache.expiration = (Default: 60000000000) + .. option:: trustengine.cache.expiration = (Default: "1m") - Expiration of cached entries in nanoseconds. - - **TODO:** this should be changed to accept values in :ref:`duration format `. + Expiration time for cached entries. .. object:: drkey diff --git a/private/trust/config/BUILD.bazel b/private/trust/config/BUILD.bazel index 7dbe003d2..4e794eed9 100644 --- a/private/trust/config/BUILD.bazel +++ b/private/trust/config/BUILD.bazel @@ -6,6 +6,7 @@ go_library( importpath = "github.com/scionproto/scion/private/trust/config", visibility = ["//visibility:public"], deps = [ + "//pkg/private/util:go_default_library", "//private/config:go_default_library", "@com_github_patrickmn_go_cache//:go_default_library", ], diff --git a/private/trust/config/config.go b/private/trust/config/config.go index 35df7d2f1..43ac04ed4 100644 --- a/private/trust/config/config.go +++ b/private/trust/config/config.go @@ -20,6 +20,7 @@ import ( "github.com/patrickmn/go-cache" + "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/private/config" ) @@ -47,20 +48,20 @@ func (cfg *Config) ConfigName() string { } type Cache struct { - Disable bool `toml:"disable,omitempty"` - Expiration time.Duration `toml:"expiration,omitempty"` + Disable bool `toml:"disable,omitempty"` + Expiration util.DurWrap `toml:"expiration,omitempty"` } func (cfg *Cache) New() *cache.Cache { if cfg.Disable { return nil } - return cache.New(cfg.Expiration, time.Minute) + return cache.New(cfg.Expiration.Duration, time.Minute) } func (cfg *Cache) InitDefaults() { - if cfg.Expiration == 0 { - cfg.Expiration = defaultExpiration + if cfg.Expiration.Duration == 0 { + cfg.Expiration.Duration = defaultExpiration } } From bfa5fe2b1354e9494d1eb96757ffe0cb490c5773 Mon Sep 17 00:00:00 2001 From: Samuel Hitz Date: Fri, 20 Oct 2023 09:00:08 +0200 Subject: [PATCH 072/255] snet/metrics: use registry in snet metrics (#4423) The options were not correctly passed in to NewSCMPErrors in snet/metrics. This commit fixes that. --- pkg/snet/metrics/metrics.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/snet/metrics/metrics.go b/pkg/snet/metrics/metrics.go index 3df7ac3fc..d70fe5b00 100644 --- a/pkg/snet/metrics/metrics.go +++ b/pkg/snet/metrics/metrics.go @@ -84,7 +84,7 @@ func NewSCIONPacketConnMetrics(opts ...Option) snet.SCIONPacketConnMetrics { ParseErrors: metrics.NewPromCounter(auto.NewCounterVec(prometheus.CounterOpts{ Name: "lib_snet_parse_error_total", Help: "Total number of parse errors"}, []string{})), - SCMPErrors: NewSCMPErrors(), + SCMPErrors: NewSCMPErrors(opts...), } } From a82e4fb9817fe30e60ee5a8740cc1075df10b438 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Mon, 30 Oct 2023 16:51:42 +0100 Subject: [PATCH 073/255] deps: bump google.golang.org/grpc, set MaxConcurrentStreams (#4424) Bump google.golang.org/grpc from 1.57.0 to 1.57.2 due to a security patch. Skipping 1.57.1, because that contained a bug. From vulnerability alert "gRPC-Go HTTP/2 Rapid Reset vulnerability": > Impact > > In affected releases of gRPC-Go, it is possible for an attacker to send > HTTP/2 requests, cancel them, and send subsequent requests, which is > valid by the HTTP/2 protocol, but would cause the gRPC-Go server to > launch more concurrent method handlers than the configured maximum > stream limit. Patches > > This vulnerability was addressed by #6703 and has been included in patch > releases: 1.56.3, 1.57.1, 1.58.3. It is also included in the latest > release, 1.59.0. > > Along with applying the patch, users should also ensure they are using > the grpc.MaxConcurrentStreams server option to apply a limit to the > server's resources used for any single connection. --- control/cmd/control/main.go | 6 +++++- daemon/cmd/daemon/main.go | 5 ++++- gateway/gateway.go | 5 ++++- go.mod | 2 +- go.sum | 4 ++-- go_deps.bzl | 4 ++-- pkg/grpc/interceptor.go | 8 ++++++++ 7 files changed, 26 insertions(+), 8 deletions(-) diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index 0be35b0b5..c5e4c70a5 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -315,8 +315,12 @@ func realMain(ctx context.Context) error { quicServer := grpc.NewServer( grpc.Creds(libgrpc.PassThroughCredentials{}), libgrpc.UnaryServerInterceptor(), + libgrpc.DefaultMaxConcurrentStreams(), + ) + tcpServer := grpc.NewServer( + libgrpc.UnaryServerInterceptor(), + libgrpc.DefaultMaxConcurrentStreams(), ) - tcpServer := grpc.NewServer(libgrpc.UnaryServerInterceptor()) // Register trust material related handlers. trustServer := &cstrustgrpc.MaterialServer{ diff --git a/daemon/cmd/daemon/main.go b/daemon/cmd/daemon/main.go index ded6ef110..5505de27b 100644 --- a/daemon/cmd/daemon/main.go +++ b/daemon/cmd/daemon/main.go @@ -251,7 +251,10 @@ func realMain(ctx context.Context) error { }} } - server := grpc.NewServer(libgrpc.UnaryServerInterceptor()) + server := grpc.NewServer( + libgrpc.UnaryServerInterceptor(), + libgrpc.DefaultMaxConcurrentStreams(), + ) sdpb.RegisterDaemonServiceServer(server, daemon.NewServer( daemon.ServerConfig{ IA: topo.IA(), diff --git a/gateway/gateway.go b/gateway/gateway.go index d2060b8de..7682e41a4 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -584,7 +584,10 @@ func (g *Gateway) Run(ctx context.Context) error { if g.Metrics != nil { paMetric = metrics.NewPromGauge(g.Metrics.PrefixesAdvertised) } - discoveryServer := grpc.NewServer(libgrpc.UnaryServerInterceptor()) + discoveryServer := grpc.NewServer( + libgrpc.UnaryServerInterceptor(), + libgrpc.DefaultMaxConcurrentStreams(), + ) gatewaypb.RegisterIPPrefixesServiceServer( discoveryServer, controlgrpc.IPPrefixServer{ diff --git a/go.mod b/go.mod index 94a5be61d..0bfb551a1 100644 --- a/go.mod +++ b/go.mod @@ -46,7 +46,7 @@ require ( golang.org/x/net v0.10.0 golang.org/x/sync v0.2.0 golang.org/x/tools v0.9.1 - google.golang.org/grpc v1.57.0 + google.golang.org/grpc v1.57.2 google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index 6048c5353..2860c3acf 100644 --- a/go.sum +++ b/go.sum @@ -772,8 +772,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.57.2 h1:uw37EN34aMFFXB2QPW7Tq6tdTbind1GpRxw5aOX3a5k= +google.golang.org/grpc v1.57.2/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 h1:ijVKWXLMbG/RK63KfOQ1lEVpEApj174fkw073gxZf3w= google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095/go.mod h1:Nr5H8+MlGWr5+xX/STzdoEqJrO+YteqFbMyCsrb6mH0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/go_deps.bzl b/go_deps.bzl index b4e2da4fa..a936afe9f 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -1410,8 +1410,8 @@ def go_deps(): "gazelle:resolve go google.golang.org/genproto/googleapis/rpc/status @org_golang_google_genproto_googleapis_rpc//status", ], importpath = "google.golang.org/grpc", - sum = "h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=", - version = "v1.57.0", + sum = "h1:uw37EN34aMFFXB2QPW7Tq6tdTbind1GpRxw5aOX3a5k=", + version = "v1.57.2", ) go_repository( name = "org_golang_google_grpc_examples", diff --git a/pkg/grpc/interceptor.go b/pkg/grpc/interceptor.go index 3fe3363fe..6fd6d8e7d 100644 --- a/pkg/grpc/interceptor.go +++ b/pkg/grpc/interceptor.go @@ -161,6 +161,14 @@ func StreamClientInterceptor() grpc.DialOption { ) } +// DefaultMaxConcurrentStreams constructs the default grpc.MaxConcurrentStreams Server Option. +// grpc-go prohibits more than MaxConcurrentStreams handlers from running at once, and setting this +// option so prevents easy resource exhaustion attacks from malicious clients. +func DefaultMaxConcurrentStreams() grpc.ServerOption { + // A very generic default value; this is the default that nginx appears to use. + return grpc.MaxConcurrentStreams(128) +} + // UnaryServerInterceptor constructs the default unary RPC server-side interceptor for // SCION control-plane applications. func UnaryServerInterceptor() grpc.ServerOption { From fa437825ee6dcbba2a084da4be8eb13f8b631a41 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Mon, 30 Oct 2023 17:26:24 +0100 Subject: [PATCH 074/255] router: extend packet processing metrics (#4422) Improve metrics for router packet processing: * Classify packets by size bucket: log2(size) * Classify packets by traffic type: incoming, outgoing, as-transit-in/out, br-transit. * Add process-level on-cpu and sleep time accounting --- .gitignore | 5 + demo/file_transfer/file_transfer.py | 12 +- go.mod | 6 +- go.sum | 12 +- go_deps.bzl | 12 +- pkg/private/processmetrics/BUILD.bazel | 60 ++++ .../processmetrics/processmetrics_linux.go | 214 +++++++++++++ .../processmetrics/processmetrics_other.go | 29 ++ router/BUILD.bazel | 1 + router/dataplane.go | 291 +++++++++--------- router/dataplane_internal_test.go | 23 +- router/dataplane_test.go | 110 +++++-- router/export_test.go | 2 + router/metrics.go | 232 +++++++++++++- tools/topology/monitoring.py | 13 +- 15 files changed, 813 insertions(+), 209 deletions(-) create mode 100644 pkg/private/processmetrics/BUILD.bazel create mode 100644 pkg/private/processmetrics/processmetrics_linux.go create mode 100644 pkg/private/processmetrics/processmetrics_other.go diff --git a/.gitignore b/.gitignore index fb8655189..e994a71ed 100644 --- a/.gitignore +++ b/.gitignore @@ -91,6 +91,11 @@ _build node_modules # gobra +####### *.vpr tmp/ logger.log + +# emacs backup files +#################### +*~ diff --git a/demo/file_transfer/file_transfer.py b/demo/file_transfer/file_transfer.py index 6207159e3..f4ede5068 100644 --- a/demo/file_transfer/file_transfer.py +++ b/demo/file_transfer/file_transfer.py @@ -66,11 +66,15 @@ def _get_br_traffic(self, endpoint): conn.request('GET', '/metrics') resp = conn.getresponse() metrics = resp.read().decode('utf-8') + total = 0 + regexp = re.compile(r"""^router_input_bytes_total{.*interface="internal".*\s(.*)$""") for line in metrics.splitlines(): - m = re.search(r"""^router_input_bytes_total{interface="internal".*\s(.*)$""", line) - if m is not None: - return float(m.group(1)) / 1024 / 1024 - return None + try: + m = regexp.search(line) + total += float(m.group(1)) / 1024 / 1024 + except (TypeError, AttributeError, ValueError): + pass + return total def setup_prepare(self): print("setting up the infrastructure") diff --git a/go.mod b/go.mod index 0bfb551a1..759cd9b13 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/pelletier/go-toml v1.9.5 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 + github.com/prometheus/procfs v0.12.0 github.com/quic-go/quic-go v0.38.1 github.com/sergi/go-diff v1.3.1 github.com/smartystreets/goconvey v1.7.2 @@ -44,7 +45,7 @@ require ( go4.org/netipx v0.0.0-20230125063823-8449b0a6169f golang.org/x/crypto v0.6.0 golang.org/x/net v0.10.0 - golang.org/x/sync v0.2.0 + golang.org/x/sync v0.3.0 golang.org/x/tools v0.9.1 google.golang.org/grpc v1.57.2 google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 @@ -97,7 +98,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect github.com/quic-go/qtls-go1-20 v0.3.3 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect @@ -112,7 +112,7 @@ require ( go.uber.org/multierr v1.8.0 // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect golang.org/x/mod v0.10.0 // indirect - golang.org/x/sys v0.8.0 // indirect + golang.org/x/sys v0.12.0 // indirect golang.org/x/text v0.9.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 2860c3acf..8fcf193fa 100644 --- a/go.sum +++ b/go.sum @@ -360,8 +360,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM= github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE= @@ -564,8 +564,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -617,8 +617,8 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/go_deps.bzl b/go_deps.bzl index a936afe9f..1d7c033a6 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -1012,8 +1012,8 @@ def go_deps(): go_repository( name = "com_github_prometheus_procfs", importpath = "github.com/prometheus/procfs", - sum = "h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=", - version = "v0.8.0", + sum = "h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=", + version = "v0.12.0", ) go_repository( name = "com_github_quic_go_qpack", @@ -1482,14 +1482,14 @@ def go_deps(): go_repository( name = "org_golang_x_sync", importpath = "golang.org/x/sync", - sum = "h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=", - version = "v0.2.0", + sum = "h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=", + version = "v0.3.0", ) go_repository( name = "org_golang_x_sys", importpath = "golang.org/x/sys", - sum = "h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=", - version = "v0.8.0", + sum = "h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=", + version = "v0.12.0", ) go_repository( name = "org_golang_x_term", diff --git a/pkg/private/processmetrics/BUILD.bazel b/pkg/private/processmetrics/BUILD.bazel new file mode 100644 index 000000000..180a3e480 --- /dev/null +++ b/pkg/private/processmetrics/BUILD.bazel @@ -0,0 +1,60 @@ +load("//tools/lint:go.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "processmetrics_linux.go", + "processmetrics_other.go", + ], + importpath = "github.com/scionproto/scion/pkg/private/processmetrics", + visibility = ["//visibility:public"], + deps = select({ + "@io_bazel_rules_go//go/platform:aix": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:android": [ + "//pkg/private/serrors:go_default_library", + "@com_github_prometheus_client_golang//prometheus:go_default_library", + "@com_github_prometheus_procfs//:go_default_library", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:illumos": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:ios": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:js": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "//pkg/private/serrors:go_default_library", + "@com_github_prometheus_client_golang//prometheus:go_default_library", + "@com_github_prometheus_procfs//:go_default_library", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "//pkg/private/serrors:go_default_library", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "//pkg/private/serrors:go_default_library", + ], + "//conditions:default": [], + }), +) diff --git a/pkg/private/processmetrics/processmetrics_linux.go b/pkg/private/processmetrics/processmetrics_linux.go new file mode 100644 index 000000000..821bd34db --- /dev/null +++ b/pkg/private/processmetrics/processmetrics_linux.go @@ -0,0 +1,214 @@ +// Copyright 2023 SCION Association +// +// 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 processmetrics provides a custom collector to export process-level +// metrics beyond what prometheus.ProcesssCollector offers. +// This implementation is restricted to Linux. The generic implementation +// does nothing. +// This code works only if the delayacct kernel feature is turned on. +// this is done by "sysctl kernel.task_delayacct=1". +// +// In order to make a fair run-to-run comparison of these metrics, we must +// relate them to the actual CPU time that was *available* to the router. +// That is, the time that the process was either running, blocked, or sleeping, +// but not "runnable" (which in unix-ese implies *not* running). +// A custom collector in pkg/processmetrics exposes the running and runnable +// metrics directly from the scheduler. +// Possibly crude example of a query that accounts for available cpu: +// +// rate(router_processed_pkts_total[1m]) +// / on (instance, job) group_left () +// (1 - rate(process_runnable_seconds_total[1m])) +// +// This shows processed_packets per available cpu seconds, as opposed to +// real time. +// Possibly crude example of a query that only looks at cpu use efficiency; +// This shows processed_packets per consumed cpu seconds: +// +// rate(router_processed_pkts_total[1m]) +// / on (instance, job) group_left () +// (rate(process_running_seconds_total[1m])) +// + +//go:build linux + +package processmetrics + +import ( + "os" + "path/filepath" + "strconv" + "syscall" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs" + + "github.com/scionproto/scion/pkg/private/serrors" +) + +var ( + // These two metrics allows to infer the amount of CPU time that was available, used or not, + // to the process: + // wallClock time = runningTime + runnableTime + sleepingTime. + // availableCPU = runningTime + sleepingTime + // Therefore AvailbleTime = wallClockTime - runnableTime. + // runningTime should be the same as uTime+sTime reported in a variety of other ways, + // but when doing calculations, better use the two data from the same source. So, collect them + // both. + runningTime = prometheus.NewDesc( + "process_running_seconds_total", + "Time the process spend running since it started (all threads summed).", + nil, nil, + ) + runnableTime = prometheus.NewDesc( + "process_runnable_seconds_total", + "Time the process spend runnable (unscheduled) since it started (all threads summed).", + nil, nil, + ) + // This metric is introspective. It's trying to gauge if we're successful in collecting the + // other two at a reasonable cost. + tasklistUpdates = prometheus.NewDesc( + "process_metrics_tasklist_updates_total", + "The number of time the processmetrics collector recreated its list of tasks.", + nil, nil, + ) +) + +// procStatCollector is a custom collector for some process-wide statistics +// that are not available in default collectors. +type procStatCollector struct { + myPid int + myProcs procfs.Procs + myTasks *os.File + lastTaskCount uint64 + taskListUpdates int64 + totalRunning uint64 + totalRunnable uint64 +} + +// UpdateStat fetches the raw per-thread scheduling metrics from /proc. +// That is: from /proc/task/*/schedstat. +// This raw data is cached for Collect to pick-up and reshape +// when prometheus scrapes. +func (c *procStatCollector) updateStat() error { + + // procfs.AllThreads is expensive (lots of garbage in its wake) and often idempotent. + // To reduce the cost, we skip doing it when we know that the threads line-up is + // unchanged. Since Go never terminates the threads it creates, if the lineup has + // changed, the count has changed. We can only get that from the syscall API. + // As soon as we get the bareFd the IOs with that file become blocking. So, the thread + // collector thread could theoretically block on the IO (not sure stating /proc results + // in any IO wait, though). + + var taskStat syscall.Stat_t + err := syscall.Fstat(int(c.myTasks.Fd()), &taskStat) + if err != nil { + return err + } + newCount := taskStat.Nlink - 2 + if newCount != c.lastTaskCount { + c.taskListUpdates++ + c.myProcs, err = procfs.AllThreads(c.myPid) + if err != nil { + return err + } + c.lastTaskCount = newCount + } + + // Sum the times of all threads. + totalRunning := uint64(0) + totalRunnable := uint64(0) + for _, p := range c.myProcs { + // The procfs API gives us no choice. For each thread, it builds an object with a + // set of stats, which we throw on the garbage pile after picking what we need. + schedStat, oneErr := p.Schedstat() + if oneErr != nil { + err = oneErr + // The only reason would be that this thread has disappeared, which doesn't + // invalidate the values from the others. So, continuing makes more sense. + continue + } + totalRunning += schedStat.RunningNanoseconds + totalRunnable += schedStat.WaitingNanoseconds + } + + c.totalRunning = totalRunning + c.totalRunnable = totalRunnable + return err +} + +// Describe tells prometheus all the metrics that this collector +// collects. +func (c *procStatCollector) Describe(ch chan<- *prometheus.Desc) { + prometheus.DescribeByCollect(c, ch) +} + +// Collect picks the necessary raw metrics from lastSchedstat +// and derives the metrics to be returned. This is invoked whenever +// prometheus scrapes. The derivation consists mostly in unit conversions. +// Because raw metrics are very few and not expensive to get, Collect +// currently calls updateStat() every time to get the latest. +func (c *procStatCollector) Collect(ch chan<- prometheus.Metric) { + _ = c.updateStat() + + ch <- prometheus.MustNewConstMetric( + runningTime, + prometheus.CounterValue, + float64(c.totalRunning)/1000000000, // Report duration in SI + ) + ch <- prometheus.MustNewConstMetric( + runnableTime, + prometheus.CounterValue, + float64(c.totalRunnable)/1000000000, // Report duration in SI + ) + ch <- prometheus.MustNewConstMetric( + tasklistUpdates, + prometheus.CounterValue, + float64(c.taskListUpdates), + ) +} + +// Init creates a new collector for process statistics. +// The collector exposes those statistics to prometheus and responds +// to scraping requests. Call this only once per process or get an error. +// It is safe to ignore errors from this but prometheus may lack some +// metrics. +func Init() error { + me := os.Getpid() + taskPath := filepath.Join(procfs.DefaultMountPoint, strconv.Itoa(me), "task") + taskDir, err := os.Open(taskPath) + if err != nil { + return serrors.WrapStr("Opening /proc/pid/task/ failed", err, + "pid", me) + } + + c := &procStatCollector{ + myPid: me, + myTasks: taskDir, + } + + err = c.updateStat() + if err != nil { + // Ditch the broken collector. It won't do anything useful. + return serrors.WrapStr("First update failed", err) + } + + // It works. Register it so prometheus milks it. + err = prometheus.Register(c) + if err != nil { + return serrors.WrapStr("Registration failed", err) + } + + return nil +} diff --git a/pkg/private/processmetrics/processmetrics_other.go b/pkg/private/processmetrics/processmetrics_other.go new file mode 100644 index 000000000..fee4922a4 --- /dev/null +++ b/pkg/private/processmetrics/processmetrics_other.go @@ -0,0 +1,29 @@ +// Copyright 2023 SCION Association +// +// 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 processmetrics provides a custom collector to export process-level +// metrics beyond what prometheus.ProcesssCollector offers. +// This is the generic implementation. It does nothing. + +//go:build !linux + +package processmetrics + +import ( + "github.com/scionproto/scion/pkg/private/serrors" +) + +func Init() error { + return serrors.New("Not supported for this platform") +} diff --git a/router/BUILD.bazel b/router/BUILD.bazel index d7ebcbc60..ed41f1d88 100644 --- a/router/BUILD.bazel +++ b/router/BUILD.bazel @@ -16,6 +16,7 @@ go_library( "//pkg/experimental/epic:go_default_library", "//pkg/log:go_default_library", "//pkg/private/common:go_default_library", + "//pkg/private/processmetrics:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/private/util:go_default_library", "//pkg/scrypto:go_default_library", diff --git a/router/dataplane.go b/router/dataplane.go index 362c298c3..2a1e06e3d 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -27,7 +27,6 @@ import ( "math/big" "net" "net/netip" - "strconv" "sync" "time" @@ -40,6 +39,7 @@ import ( "github.com/scionproto/scion/pkg/drkey" libepic "github.com/scionproto/scion/pkg/experimental/epic" "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/private/processmetrics" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/scrypto" @@ -110,7 +110,7 @@ type DataPlane struct { mtx sync.Mutex running bool Metrics *Metrics - forwardingMetrics map[uint16]forwardingMetrics + forwardingMetrics map[uint16]interfaceMetrics ExperimentalSCMPAuthentication bool @@ -397,7 +397,7 @@ func (d *DataPlane) AddSvc(svc addr.SVC, a *net.UDPAddr) error { } d.svc.AddSvc(svc, a) if d.Metrics != nil { - labels := serviceMetricLabels(d.localIA, svc) + labels := serviceLabels(d.localIA, svc) d.Metrics.ServiceInstanceChanges.With(labels).Add(1) d.Metrics.ServiceInstanceCount.With(labels).Add(1) } @@ -416,7 +416,7 @@ func (d *DataPlane) DelSvc(svc addr.SVC, a *net.UDPAddr) error { } d.svc.DelSvc(svc, a) if d.Metrics != nil { - labels := serviceMetricLabels(d.localIA, svc) + labels := serviceLabels(d.localIA, svc) d.Metrics.ServiceInstanceChanges.With(labels).Add(1) d.Metrics.ServiceInstanceCount.With(labels).Add(-1) } @@ -589,9 +589,13 @@ type packet struct { // The address to where we are forwarding the packet. // Will be set by the processing routine dstAddr *net.UDPAddr - // The ingress on which this packet arrived. Will be - // set by the receiver - ingress uint16 + // The ingress on which this packet arrived. This is + // set by the receiver. + ingress uint16 + // The type of traffic. This is used for metrics at the forwarding stage, but is most + // economically determined at the processing stage. So transport it here. + trafficType trafficType + // The goods rawPacket []byte } @@ -610,23 +614,24 @@ func (d *DataPlane) runReceiver(ifID uint16, conn BatchConn, cfg *RunConfig, } msgs := underlayconn.NewReadMessages(cfg.BatchSize) - numReusable := 0 // unused buffers from previous loop - metrics := d.forwardingMetrics[ifID] + numReusable := 0 // unused buffers from previous loop + metrics := d.forwardingMetrics[ifID] // If receiver exists, fw metrics exist too. flowIDBuffer := make([]byte, 3) hasher := fnv.New32a() enqueueForProcessing := func(pkt ipv4.Message) { - metrics.InputPacketsTotal.Inc() - metrics.InputBytesTotal.Add(float64(pkt.N)) - srcAddr := pkt.Addr.(*net.UDPAddr) + size := pkt.N + sc := classOfSize(size) + metrics[sc].InputPacketsTotal.Inc() + metrics[sc].InputBytesTotal.Add(float64(size)) procID, err := computeProcID(pkt.Buffers[0], cfg.NumProcessors, randomValue, flowIDBuffer, hasher) if err != nil { log.Debug("Error while computing procID", "err", err) d.returnPacketToPool(pkt.Buffers[0]) - metrics.DroppedPacketsInvalid.Inc() + metrics[sc].DroppedPacketsInvalid.Inc() return } outPkt := packet{ @@ -638,7 +643,7 @@ func (d *DataPlane) runReceiver(ifID uint16, conn BatchConn, cfg *RunConfig, case procQs[procID] <- outPkt: default: d.returnPacketToPool(pkt.Buffers[0]) - metrics.DroppedPacketsBusyProcessor.Inc() + metrics[sc].DroppedPacketsBusyProcessor.Inc() } } @@ -699,9 +704,12 @@ func (d *DataPlane) runProcessor(id int, q <-chan packet, if !ok { continue } - metrics := d.forwardingMetrics[p.ingress] result, err := processor.processPkt(p.rawPacket, p.srcAddr, p.ingress) + + sc := classOfSize(len(p.rawPacket)) + metrics := d.forwardingMetrics[p.ingress][sc] metrics.ProcessedPackets.Inc() + egress := result.EgressID switch { case err == nil: @@ -732,7 +740,7 @@ func (d *DataPlane) runProcessor(id int, q <-chan packet, } p.rawPacket = result.OutPkt p.dstAddr = result.OutAddr - + p.trafficType = result.TrafficType select { case fwCh <- p: default: @@ -753,8 +761,9 @@ func (d *DataPlane) runSlowPathProcessor(id int, q <-chan slowPacket, if !ok { continue } - metrics := d.forwardingMetrics[p.packet.ingress] res, err := processor.processPacket(p) + sc := classOfSize(len(p.rawPacket)) + metrics := d.forwardingMetrics[p.packet.ingress][sc] if err != nil { log.Debug("Error processing packet", "err", err) metrics.DroppedPacketsInvalid.Inc() @@ -829,6 +838,17 @@ func (p *slowPathPacketProcessor) reset() { p.e2eLayer = slayers.EndToEndExtnSkipper{} } +// processResults carries what could be determined while processing +// a packet. In most cases of error, all fields are left to their +// zero value. +type processResult struct { + EgressID uint16 + OutAddr *net.UDPAddr + OutPkt []byte + SlowPathRequest slowPathRequest + TrafficType trafficType +} + func (p *slowPathPacketProcessor) processPacket(pkt slowPacket) (processResult, error) { var err error p.reset() @@ -887,64 +907,95 @@ func (p *slowPathPacketProcessor) processPacket(pkt slowPacket) (processResult, } } -func (d *DataPlane) runForwarder(ifID uint16, conn BatchConn, - cfg *RunConfig, c <-chan packet) { +func updateOutputMetrics(metrics interfaceMetrics, packets []packet) { + // We need to collect stats by traffic type and size class. + // Try to reduce the metrics lookup penalty by using some + // simpler staging data structure. + writtenPkts := [ttMax][maxSizeClass]int{} + writtenBytes := [ttMax][maxSizeClass]int{} + for _, p := range packets { + s := len(p.rawPacket) + sc := classOfSize(s) + tt := p.trafficType + writtenPkts[tt][sc]++ + writtenBytes[tt][sc] += s + } + for t := ttOther; t < ttMax; t++ { + for sc := minSizeClass; sc < maxSizeClass; sc++ { + if writtenPkts[t][sc] > 0 { + metrics[sc].Output[t].OutputPacketsTotal.Add(float64(writtenPkts[t][sc])) + metrics[sc].Output[t].OutputBytesTotal.Add(float64(writtenBytes[t][sc])) + } + } + } +} + +func (d *DataPlane) runForwarder(ifID uint16, conn BatchConn, cfg *RunConfig, c <-chan packet) { log.Debug("Initialize forwarder for", "interface", ifID) - writeMsgs := make(underlayconn.Messages, cfg.BatchSize) - for i := range writeMsgs { - writeMsgs[i].Buffers = make([][]byte, 1) + + // We use this somewhat like a ring buffer. + pkts := make([]packet, cfg.BatchSize) + + // We use this as a temporary buffer, but allocate it just once + // to save on garbage handling. + msgs := make(underlayconn.Messages, cfg.BatchSize) + for i := range msgs { + msgs[i].Buffers = make([][]byte, 1) } + metrics := d.forwardingMetrics[ifID] - remaining := 0 + toWrite := 0 for d.running { - available := readUpTo(c, cfg.BatchSize-remaining, remaining == 0, - writeMsgs[remaining:]) - available += remaining - written, _ := conn.WriteBatch(writeMsgs[:available], 0) + toWrite += readUpTo(c, cfg.BatchSize-toWrite, toWrite == 0, pkts[toWrite:]) + + // Turn the packets into underlay messages that WriteBatch can send. + for i, p := range pkts[:toWrite] { + msgs[i].Buffers[0] = p.rawPacket + msgs[i].Addr = nil + if p.dstAddr != nil { + msgs[i].Addr = p.dstAddr + } + } + written, _ := conn.WriteBatch(msgs[:toWrite], 0) if written < 0 { // WriteBatch returns -1 on error, we just consider this as // 0 packets written written = 0 } - writtenBytes := 0 - for i := range writeMsgs[:written] { - writtenBytes += len(writeMsgs[i].Buffers[0]) - d.returnPacketToPool(writeMsgs[i].Buffers[0]) + + updateOutputMetrics(metrics, pkts[:written]) + + for _, p := range pkts[:written] { + d.returnPacketToPool(p.rawPacket) } - metrics.OutputPacketsTotal.Add(float64(written)) - metrics.OutputBytesTotal.Add(float64(writtenBytes)) - if written != available { - metrics.DroppedPacketsInvalid.Inc() - d.returnPacketToPool(writeMsgs[written].Buffers[0]) - remaining = available - written - 1 - for i := 0; i < remaining; i++ { - writeMsgs[i].Buffers[0] = writeMsgs[i+written+1].Buffers[0] - writeMsgs[i].Addr = writeMsgs[i+written+1].Addr + if written != toWrite { + // Only one is dropped at this time. We'll retry the rest. + sc := classOfSize(len(pkts[written].rawPacket)) + metrics[sc].DroppedPacketsInvalid.Inc() + d.returnPacketToPool(pkts[written].rawPacket) + toWrite -= (written + 1) + // Shift the leftovers to the head of the buffers. + for i := 0; i < toWrite; i++ { + pkts[i] = pkts[i+written+1] } + } else { - remaining = 0 + toWrite = 0 } } } -func readUpTo(c <-chan packet, n int, needsBlocking bool, msg []ipv4.Message) int { - assign := func(p packet, m *ipv4.Message) { - m.Buffers[0] = p.rawPacket - m.Addr = nil - if p.dstAddr != nil { - m.Addr = p.dstAddr - } - } +func readUpTo(c <-chan packet, n int, needsBlocking bool, pkts []packet) int { i := 0 if needsBlocking { p, ok := <-c if !ok { return i } - assign(p, &msg[i]) + pkts[i] = p i++ } @@ -954,7 +1005,7 @@ func readUpTo(c <-chan packet, n int, needsBlocking bool, msg []ipv4.Message) in if !ok { return i } - assign(p, &msg[i]) + pkts[i] = p default: return i } @@ -963,29 +1014,6 @@ func readUpTo(c <-chan packet, n int, needsBlocking bool, msg []ipv4.Message) in return i } -// initMetrics initializes the metrics related to packet forwarding. The -// counters are already instantiated for all the relevant interfaces so this -// will not have to be repeated during packet forwarding. -func (d *DataPlane) initMetrics() { - d.forwardingMetrics = make(map[uint16]forwardingMetrics) - labels := interfaceToMetricLabels(0, d.localIA, d.neighborIAs) - d.forwardingMetrics[0] = initForwardingMetrics(d.Metrics, labels) - for id := range d.external { - if _, notOwned := d.internalNextHops[id]; notOwned { - continue - } - labels = interfaceToMetricLabels(id, d.localIA, d.neighborIAs) - d.forwardingMetrics[id] = initForwardingMetrics(d.Metrics, labels) - } -} - -type processResult struct { - EgressID uint16 - OutAddr *net.UDPAddr - OutPkt []byte - SlowPathRequest slowPathRequest -} - func newPacketProcessor(d *DataPlane) *scionPacketProcessor { p := &scionPacketProcessor{ d: d, @@ -1035,6 +1063,7 @@ func (p *scionPacketProcessor) processPkt(rawPkt []byte, if err != nil { return processResult{}, err } + pld := p.lastLayer.LayerPayload() pathType := p.scionLayer.PathType @@ -1782,17 +1811,20 @@ func (p *scionPacketProcessor) process() (processResult, error) { if r, err := p.handleIngressRouterAlert(); err != nil { return r, err } - // Inbound: pkts destined to the local IA. + // Inbound: pkt destined to the local IA. if p.scionLayer.DstIA == p.d.localIA { a, r, err := p.resolveInbound() if err != nil { return r, err } - return processResult{OutAddr: a, OutPkt: p.rawPkt}, nil + return processResult{OutAddr: a, OutPkt: p.rawPkt, TrafficType: ttIn}, nil } - // Outbound: pkts leaving the local IA. - // BRTransit: pkts leaving from the same BR different interface. + // Outbound: pkt leaving the local IA. This Could be: + // * Pure outbound: from this AS, in via internal, out via external. + // * ASTransit in: from another AS, in via external, out via internal to other BR. + // * ASTransit out: from another AS, in via internal from other BR, out via external. + // * BRTransit: from another AS, in via external, out via external. if p.path.IsXover() && !p.peering { // An effective cross-over is a change of segment other than at // a peering hop. @@ -1823,14 +1855,27 @@ func (p *scionPacketProcessor) process() (processResult, error) { } egressID := p.egressInterface() if _, ok := p.d.external[egressID]; ok { + // Not ASTransit in if err := p.processEgress(); err != nil { return processResult{}, err } - return processResult{EgressID: egressID, OutPkt: p.rawPkt}, nil + // Finish deciding the trafficType... + var tt trafficType + if p.scionLayer.SrcIA == p.d.localIA { + // Pure outbound + tt = ttOut + } else if p.ingressID == 0 { + // ASTransit out + tt = ttOutTransit + } else { + // Therefore it is BRTransit + tt = ttBrTransit + } + return processResult{EgressID: egressID, OutPkt: p.rawPkt, TrafficType: tt}, nil } - // ASTransit: pkts leaving from another AS BR. + // ASTransit in: pkt leaving this AS through another BR. if a, ok := p.d.internalNextHops[egressID]; ok { - return processResult{OutAddr: a, OutPkt: p.rawPkt}, nil + return processResult{OutAddr: a, OutPkt: p.rawPkt, TrafficType: ttInTransit}, nil } errCode := slayers.SCMPCodeUnknownHopFieldEgress if !p.infoField.ConsDir { @@ -2365,69 +2410,25 @@ func nextHdr(layer gopacket.DecodingLayer) slayers.L4ProtocolType { } } -// forwardingMetrics contains the subset of Metrics relevant for forwarding, -// instantiated with some interface-specific labels. -type forwardingMetrics struct { - InputBytesTotal prometheus.Counter - OutputBytesTotal prometheus.Counter - InputPacketsTotal prometheus.Counter - OutputPacketsTotal prometheus.Counter - DroppedPacketsInvalid prometheus.Counter - DroppedPacketsBusyProcessor prometheus.Counter - DroppedPacketsBusyForwarder prometheus.Counter - DroppedPacketsBusySlowPath prometheus.Counter - ProcessedPackets prometheus.Counter -} - -func initForwardingMetrics(metrics *Metrics, labels prometheus.Labels) forwardingMetrics { - c := forwardingMetrics{ - InputBytesTotal: metrics.InputBytesTotal.With(labels), - InputPacketsTotal: metrics.InputPacketsTotal.With(labels), - OutputBytesTotal: metrics.OutputBytesTotal.With(labels), - OutputPacketsTotal: metrics.OutputPacketsTotal.With(labels), - ProcessedPackets: metrics.ProcessedPackets.With(labels), - } - labels["reason"] = "invalid" - c.DroppedPacketsInvalid = metrics.DroppedPacketsTotal.With(labels) - labels["reason"] = "busy_processor" - c.DroppedPacketsBusyProcessor = metrics.DroppedPacketsTotal.With(labels) - labels["reason"] = "busy_forwarder" - c.DroppedPacketsBusyForwarder = metrics.DroppedPacketsTotal.With(labels) - labels["reason"] = "busy_slow_path" - c.DroppedPacketsBusySlowPath = metrics.DroppedPacketsTotal.With(labels) - - c.InputBytesTotal.Add(0) - c.InputPacketsTotal.Add(0) - c.OutputBytesTotal.Add(0) - c.OutputPacketsTotal.Add(0) - c.DroppedPacketsInvalid.Add(0) - c.DroppedPacketsBusyProcessor.Add(0) - c.DroppedPacketsBusyForwarder.Add(0) - c.DroppedPacketsBusySlowPath.Add(0) - c.ProcessedPackets.Add(0) - return c -} - -func interfaceToMetricLabels(id uint16, localIA addr.IA, - neighbors map[uint16]addr.IA) prometheus.Labels { - - if id == 0 { - return prometheus.Labels{ - "isd_as": localIA.String(), - "interface": "internal", - "neighbor_isd_as": localIA.String(), - } - } - return prometheus.Labels{ - "isd_as": localIA.String(), - "interface": strconv.FormatUint(uint64(id), 10), - "neighbor_isd_as": neighbors[id].String(), - } -} - -func serviceMetricLabels(localIA addr.IA, svc addr.SVC) prometheus.Labels { - return prometheus.Labels{ - "isd_as": localIA.String(), - "service": svc.BaseString(), +// initMetrics initializes the metrics related to packet forwarding. The counters are already +// instantiated for all the relevant interfaces so this will not have to be repeated during packet +// forwarding. +func (d *DataPlane) initMetrics() { + d.forwardingMetrics = make(map[uint16]interfaceMetrics) + d.forwardingMetrics[0] = newInterfaceMetrics(d.Metrics, 0, d.localIA, d.neighborIAs) + for id := range d.external { + if _, notOwned := d.internalNextHops[id]; notOwned { + continue + } + d.forwardingMetrics[id] = newInterfaceMetrics(d.Metrics, id, d.localIA, d.neighborIAs) + } + + // Start our custom /proc/pid/stat collector to export iowait time and (in the future) other + // process-wide metrics that prometheus does not. + err := processmetrics.Init() + + // we can live without these metrics. Just log the error. + if err != nil { + log.Error("Could not initialize processmetrics", "err", err) } } diff --git a/router/dataplane_internal_test.go b/router/dataplane_internal_test.go index 6e92a8219..1b51607f4 100644 --- a/router/dataplane_internal_test.go +++ b/router/dataplane_internal_test.go @@ -421,6 +421,12 @@ func TestSlowPathProcessing(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() payload := []byte("actualpayloadbytes") + + // ProcessPacket assumes some pre-conditions: + // * The ingress interface has to exist. This fake map is good for the test cases we have. + // * InternalNextHops may not be nil. Empty is ok for all the test cases we have. + fakeExternalInterfaces := map[uint16]BatchConn{1: nil} + fakeInternalNextHops := map[uint16]*net.UDPAddr{} testCases := map[string]struct { mockMsg func() []byte prepareDP func(*gomock.Controller) *DataPlane @@ -430,9 +436,12 @@ func TestSlowPathProcessing(t *testing.T) { }{ "svc nobackend": { prepareDP: func(ctrl *gomock.Controller) *DataPlane { - return NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, + return NewDP(fakeExternalInterfaces, + nil, mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, map[addr.SVC][]*net.UDPAddr{}, - xtest.MustParseIA("1-ff00:0:110"), nil, testKey) + xtest.MustParseIA("1-ff00:0:110"), + nil, testKey) }, mockMsg: func() []byte { spkt := prepBaseMsg(t, payload, 0) @@ -452,7 +461,9 @@ func TestSlowPathProcessing(t *testing.T) { }, "svc invalid": { prepareDP: func(ctrl *gomock.Controller) *DataPlane { - return NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, + return NewDP(fakeExternalInterfaces, + nil, mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, map[addr.SVC][]*net.UDPAddr{}, xtest.MustParseIA("1-ff00:0:110"), nil, testKey) }, @@ -474,7 +485,9 @@ func TestSlowPathProcessing(t *testing.T) { }, "invalid dest": { prepareDP: func(ctrl *gomock.Controller) *DataPlane { - return NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, + return NewDP(fakeExternalInterfaces, + nil, mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, map[addr.SVC][]*net.UDPAddr{}, xtest.MustParseIA("1-ff00:0:110"), nil, testKey) }, @@ -500,6 +513,8 @@ func TestSlowPathProcessing(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() dp := tc.prepareDP(ctrl) + dp.initMetrics() + rawPacket := tc.mockMsg() var srcAddr *net.UDPAddr diff --git a/router/dataplane_test.go b/router/dataplane_test.go index 57f3b20dd..baf163fb5 100644 --- a/router/dataplane_test.go +++ b/router/dataplane_test.go @@ -576,6 +576,13 @@ func TestProcessPkt(t *testing.T) { epicTS, err := libepic.CreateTimestamp(now, now) require.NoError(t, err) + // ProcessPacket assumes some pre-conditions: + // * The ingress interface has to exist. This fake map is good for most test cases. + // Others need a custom one. + // * InternalNextHops may not be nil. Empty is ok (sufficient unless testing AS transit). + fakeExternalInterfaces := map[uint16]router.BatchConn{1: nil, 2: nil, 3: nil} + fakeInternalNextHops := map[uint16]*net.UDPAddr{} + testCases := map[string]struct { mockMsg func(bool) *ipv4.Message prepareDP func(*gomock.Controller) *router.DataPlane @@ -585,8 +592,10 @@ func TestProcessPkt(t *testing.T) { }{ "inbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + return router.NewDP(fakeExternalInterfaces, + nil, mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, dpath := prepBaseMsg(now) @@ -596,7 +605,7 @@ func TestProcessPkt(t *testing.T) { dpath.HopFields = []path.HopField{ {ConsIngress: 41, ConsEgress: 40}, {ConsIngress: 31, ConsEgress: 30}, - {ConsIngress: 01, ConsEgress: 0}, + {ConsIngress: 1, ConsEgress: 0}, } dpath.Base.PathMeta.CurrHF = 2 dpath.HopFields[2].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[2]) @@ -620,7 +629,9 @@ func TestProcessPkt(t *testing.T) { map[uint16]topology.LinkType{ 1: topology.Child, }, - nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + nil, + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, dpath := prepBaseMsg(now) @@ -650,13 +661,16 @@ func TestProcessPkt(t *testing.T) { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP( map[uint16]router.BatchConn{ + uint16(1): mock_router.NewMockBatchConn(ctrl), uint16(2): mock_router.NewMockBatchConn(ctrl), }, map[uint16]topology.LinkType{ 1: topology.Parent, 2: topology.Child, }, - nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + nil, + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, dpath := prepBaseMsg(now) @@ -685,12 +699,15 @@ func TestProcessPkt(t *testing.T) { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP( map[uint16]router.BatchConn{ + uint16(1): mock_router.NewMockBatchConn(ctrl), uint16(2): mock_router.NewMockBatchConn(ctrl), }, map[uint16]topology.LinkType{ 2: topology.Parent, 1: topology.Child, - }, nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + }, nil, + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, dpath := prepBaseMsg(now) @@ -720,13 +737,16 @@ func TestProcessPkt(t *testing.T) { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP( map[uint16]router.BatchConn{ + uint16(1): mock_router.NewMockBatchConn(ctrl), uint16(2): mock_router.NewMockBatchConn(ctrl), }, map[uint16]topology.LinkType{ 1: topology.Peer, 2: topology.Child, }, - nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + nil, + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { // Story: the packet just left segment 0 which ends at @@ -792,12 +812,15 @@ func TestProcessPkt(t *testing.T) { return router.NewDP( map[uint16]router.BatchConn{ uint16(1): mock_router.NewMockBatchConn(ctrl), + uint16(2): mock_router.NewMockBatchConn(ctrl), }, map[uint16]topology.LinkType{ 1: topology.Peer, 2: topology.Child, }, - nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + nil, + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { // Story: the packet lands on the last (peering) hop of @@ -870,13 +893,16 @@ func TestProcessPkt(t *testing.T) { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP( map[uint16]router.BatchConn{ + uint16(1): mock_router.NewMockBatchConn(ctrl), uint16(2): mock_router.NewMockBatchConn(ctrl), }, map[uint16]topology.LinkType{ 1: topology.Peer, 2: topology.Child, }, - nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + nil, + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { // Story: the packet just left hop 1 (the first hop @@ -946,12 +972,15 @@ func TestProcessPkt(t *testing.T) { return router.NewDP( map[uint16]router.BatchConn{ uint16(1): mock_router.NewMockBatchConn(ctrl), + uint16(2): mock_router.NewMockBatchConn(ctrl), }, map[uint16]topology.LinkType{ 1: topology.Peer, 2: topology.Child, }, - nil, nil, nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + nil, + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { // Story: the packet lands on the second (non-peering) hop of @@ -1029,7 +1058,12 @@ func TestProcessPkt(t *testing.T) { }, "astransit direct": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, + return router.NewDP( + map[uint16]router.BatchConn{ + uint16(1): mock_router.NewMockBatchConn(ctrl), + // Interface 3 isn't in the external interfaces of this router + // another router has it. + }, map[uint16]topology.LinkType{ 1: topology.Core, 3: topology.Core, @@ -1055,12 +1089,15 @@ func TestProcessPkt(t *testing.T) { return ret }, srcInterface: 1, - egressInterface: 0, + egressInterface: 0, // Internal forward to the egress router assertFunc: assert.NoError, }, "astransit xover": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, + return router.NewDP( + map[uint16]router.BatchConn{ + uint16(51): mock_router.NewMockBatchConn(ctrl), + }, map[uint16]topology.LinkType{ 51: topology.Child, 3: topology.Core, @@ -1107,13 +1144,15 @@ func TestProcessPkt(t *testing.T) { ret.Flags, ret.NN, ret.N, ret.OOB = 0, 0, 0, nil return ret }, - srcInterface: 51, - egressInterface: 0, + srcInterface: 51, // == consEgress, bc non-consdir + egressInterface: 0, // Cross-over. The egress happens in the next segment. assertFunc: assert.NoError, }, "svc": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, + return router.NewDP(fakeExternalInterfaces, + nil, mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, map[addr.SVC][]*net.UDPAddr{ addr.SvcCS: { &net.UDPAddr{ @@ -1150,7 +1189,7 @@ func TestProcessPkt(t *testing.T) { "onehop inbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP( - nil, + fakeExternalInterfaces, nil, mock_router.NewMockBatchConn(ctrl), nil, map[addr.SVC][]*net.UDPAddr{ @@ -1213,7 +1252,9 @@ func TestProcessPkt(t *testing.T) { "onehop inbound invalid src": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { return router.NewDP( - nil, nil, nil, nil, nil, + fakeExternalInterfaces, + nil, nil, + fakeInternalNextHops, nil, xtest.MustParseIA("1-ff00:0:110"), map[uint16]addr.IA{ uint16(1): xtest.MustParseIA("1-ff00:0:111"), @@ -1243,7 +1284,7 @@ func TestProcessPkt(t *testing.T) { } return toMsg(t, spkt, dpath) }, - srcInterface: 1, + srcInterface: 2, egressInterface: 21, assertFunc: assert.Error, }, @@ -1254,7 +1295,8 @@ func TestProcessPkt(t *testing.T) { uint16(1): mock_router.NewMockBatchConn(ctrl), }, nil, - mock_router.NewMockBatchConn(ctrl), nil, + mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, map[addr.SVC][]*net.UDPAddr{ addr.SvcCS: {&net.UDPAddr{ IP: net.ParseIP("172.0.2.10"), @@ -1314,8 +1356,8 @@ func TestProcessPkt(t *testing.T) { uint16(2): mock_router.NewMockBatchConn(ctrl), }, nil, - mock_router.NewMockBatchConn(ctrl), nil, - nil, + mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, nil, xtest.MustParseIA("1-ff00:0:110"), map[uint16]addr.IA{ uint16(2): xtest.MustParseIA("1-ff00:0:111"), @@ -1356,8 +1398,10 @@ func TestProcessPkt(t *testing.T) { }, "epic inbound": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + return router.NewDP(fakeExternalInterfaces, + nil, mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, epicpath, dpath := prepEpicMsg(t, @@ -1372,8 +1416,10 @@ func TestProcessPkt(t *testing.T) { }, "epic malformed path": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + return router.NewDP(fakeExternalInterfaces, + nil, mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, epicpath, dpath := prepEpicMsg(t, @@ -1389,8 +1435,10 @@ func TestProcessPkt(t *testing.T) { }, "epic invalid timestamp": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + return router.NewDP(fakeExternalInterfaces, + nil, mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, epicpath, dpath := prepEpicMsg(t, @@ -1408,8 +1456,10 @@ func TestProcessPkt(t *testing.T) { }, "epic invalid LHVF": { prepareDP: func(ctrl *gomock.Controller) *router.DataPlane { - return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil, - nil, xtest.MustParseIA("1-ff00:0:110"), nil, key) + return router.NewDP(fakeExternalInterfaces, + nil, mock_router.NewMockBatchConn(ctrl), + fakeInternalNextHops, nil, + xtest.MustParseIA("1-ff00:0:110"), nil, key) }, mockMsg: func(afterProcessing bool) *ipv4.Message { spkt, epicpath, dpath := prepEpicMsg(t, diff --git a/router/export_test.go b/router/export_test.go index a82d01e5a..f8134b4a3 100644 --- a/router/export_test.go +++ b/router/export_test.go @@ -58,10 +58,12 @@ func NewDP( svc: &services{m: svc}, internal: internal, internalIP: netip.MustParseAddr("198.51.100.1"), + Metrics: metrics, } if err := dp.SetKey(key); err != nil { panic(err) } + dp.initMetrics() return dp } diff --git a/router/metrics.go b/router/metrics.go index 71a09a03c..df7af4c74 100644 --- a/router/metrics.go +++ b/router/metrics.go @@ -15,8 +15,14 @@ package router import ( + "math/bits" + "strconv" + "strings" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" + + "github.com/scionproto/scion/pkg/addr" ) // Metrics defines the data-plane metrics for the BR. @@ -39,8 +45,8 @@ type Metrics struct { SiblingBFDStateChanges *prometheus.CounterVec } -// NewMetrics initializes the metrics for the Border Router, and registers them -// with the default registry. +// NewMetrics initializes the metrics for the Border Router, and registers them with the default +// registry. func NewMetrics() *Metrics { return &Metrics{ ProcessedPackets: promauto.NewCounterVec( @@ -48,42 +54,42 @@ func NewMetrics() *Metrics { Name: "router_processed_pkts_total", Help: "Total number of packets processed by the processor", }, - []string{"interface", "isd_as", "neighbor_isd_as"}, + []string{"interface", "isd_as", "neighbor_isd_as", "sizeclass"}, ), InputBytesTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "router_input_bytes_total", Help: "Total number of bytes received", }, - []string{"interface", "isd_as", "neighbor_isd_as"}, + []string{"interface", "isd_as", "neighbor_isd_as", "sizeclass"}, ), OutputBytesTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "router_output_bytes_total", Help: "Total number of bytes sent.", }, - []string{"interface", "isd_as", "neighbor_isd_as"}, + []string{"interface", "isd_as", "neighbor_isd_as", "sizeclass", "type"}, ), InputPacketsTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "router_input_pkts_total", Help: "Total number of packets received", }, - []string{"interface", "isd_as", "neighbor_isd_as"}, + []string{"interface", "isd_as", "neighbor_isd_as", "sizeclass"}, ), OutputPacketsTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "router_output_pkts_total", Help: "Total number of packets sent.", }, - []string{"interface", "isd_as", "neighbor_isd_as"}, + []string{"interface", "isd_as", "neighbor_isd_as", "sizeclass", "type"}, ), DroppedPacketsTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "router_dropped_pkts_total", Help: "Total number of packets dropped by the router.", }, - []string{"interface", "isd_as", "neighbor_isd_as", "reason"}, + []string{"interface", "isd_as", "neighbor_isd_as", "sizeclass", "reason"}, ), InterfaceUp: promauto.NewGaugeVec( prometheus.GaugeOpts{ @@ -159,3 +165,213 @@ func NewMetrics() *Metrics { ), } } + +// trafficType labels traffic as being of either of the following types: in, out, inTransit, +// outTransit, brTransit. inTransit or outTransit means that traffic is crossing the local AS via +// two routers. If the router being observed is the one receiving the packet from the outside, then +// the type is inTransit; else it is outTransit. brTransit means that traffic is crossing only the +// observed router. Non-scion traffic or somehow malformed traffic has type Other. +type trafficType uint8 + +const ( + ttOther trafficType = iota + ttIn + ttOut + ttInTransit + ttOutTransit + ttBrTransit + ttMax +) + +// Returns a human-friendly representation of the given traffic type. +func (t trafficType) String() string { + switch t { + case ttIn: + return "in" + case ttOut: + return "out" + case ttInTransit: + return "in_transit" + case ttOutTransit: + return "out_transit" + case ttBrTransit: + return "br_transit" + } + return "other" +} + +// sizeClass is the number of bits needed to represent some given size. This is quicker than +// computing Log2 and serves the same purpose. +type sizeClass uint8 + +// maxSizeClass is the smallest NOT-supported sizeClass. This must be enough to support the largest +// valid packet size (defined by bufSize). Since this must be a constant (to allow efficient +// fixed-sized arrays), we have to assert it's large enough for bufSize. Just in case we do get +// packets larger than bufSize, they are simply put in the last class. +const maxSizeClass sizeClass = 15 + +// This will failto compile if bufSize cannot fit in (maxSizeClass - 1) bits. +const _ = uint(1<<(maxSizeClass-1) - 1 - bufSize) + +// minSizeClass is the smallest sizeClass that we care about. +// All smaller classes are conflated with this one. +const minSizeClass sizeClass = 6 + +func classOfSize(pktSize int) sizeClass { + cs := sizeClass(bits.Len32(uint32(pktSize))) + if cs > maxSizeClass-1 { + return maxSizeClass - 1 + } + if cs <= minSizeClass { + return minSizeClass + } + return cs +} + +// Returns a human-friendly representation of the given size class. Avoid bracket notation to make +// the values possibly easier to use in monitoring queries. +func (sc sizeClass) String() string { + low := strconv.Itoa((1 << sc) >> 1) + high := strconv.Itoa((1 << sc) - 1) + if sc == minSizeClass { + low = "0" + } + if sc == maxSizeClass { + high = "inf" + } + + return strings.Join([]string{low, high}, "_") +} + +// interfaceMetrics is the set of metrics that are relevant for one given interface. It is a map +// that associates each (traffic-type, size-class) pair with the set of metrics belonging to that +// interface that have these label values. This set of metrics is itself a trafficMetric structure. +// Explanation: Metrics are labeled by interface, local-as, neighbor-as, packet size, and (for +// output metrics only) traffic type. Instances are grouped in a hierarchical manner for efficient +// access by the using code. forwardingMetrics is a map of interface to interfaceMetrics. To access +// a specific InputPacketsTotal counter, one refers to: +// +// dataplane.forwardingMetrics[interface][size-class]. +// +// trafficMetrics.Output is an array of outputMetrics indexed by traffic type. +type interfaceMetrics map[sizeClass]trafficMetrics + +// trafficMetrics groups all the metrics instances that all share the same interface AND +// sizeClass label values (but have different names - i.e. they count different things). +type trafficMetrics struct { + InputBytesTotal prometheus.Counter + InputPacketsTotal prometheus.Counter + DroppedPacketsInvalid prometheus.Counter + DroppedPacketsBusyProcessor prometheus.Counter + DroppedPacketsBusyForwarder prometheus.Counter + DroppedPacketsBusySlowPath prometheus.Counter + ProcessedPackets prometheus.Counter + Output [ttMax]outputMetrics +} + +// outputMetrics groups all the metrics about traffic that has reached the output stage. Metrics +// instances in each of these all have the same interface AND sizeClass AND trafficType label +// values. +type outputMetrics struct { + OutputBytesTotal prometheus.Counter + OutputPacketsTotal prometheus.Counter +} + +func newInterfaceMetrics( + metrics *Metrics, + id uint16, + localIA addr.IA, + neighbors map[uint16]addr.IA) interfaceMetrics { + + ifLabels := interfaceLabels(0, localIA, neighbors) + m := interfaceMetrics{} + for sc := minSizeClass; sc < maxSizeClass; sc++ { + scLabels := prometheus.Labels{"sizeclass": sc.String()} + m[sc] = newTrafficMetrics(metrics, ifLabels, scLabels) + } + return m +} + +func newTrafficMetrics( + metrics *Metrics, + ifLabels prometheus.Labels, + scLabels prometheus.Labels) trafficMetrics { + + c := trafficMetrics{ + InputBytesTotal: metrics.InputBytesTotal.MustCurryWith(ifLabels).With(scLabels), + InputPacketsTotal: metrics.InputPacketsTotal.MustCurryWith(ifLabels).With(scLabels), + ProcessedPackets: metrics.ProcessedPackets.MustCurryWith(ifLabels).With(scLabels), + } + + // Output metrics have the extra "trafficType" label. + for t := ttOther; t < ttMax; t++ { + ttLabels := prometheus.Labels{"type": t.String()} + c.Output[t] = newOutputMetrics(metrics, ifLabels, scLabels, ttLabels) + } + + // Dropped metrics have the extra "Reason" label. + reasonMap := map[string]string{} + + reasonMap["reason"] = "invalid" + c.DroppedPacketsInvalid = + metrics.DroppedPacketsTotal.MustCurryWith(ifLabels).MustCurryWith(scLabels).With(reasonMap) + + reasonMap["reason"] = "busy_processor" + c.DroppedPacketsBusyProcessor = + metrics.DroppedPacketsTotal.MustCurryWith(ifLabels).MustCurryWith(scLabels).With(reasonMap) + + reasonMap["reason"] = "busy_forwarder" + c.DroppedPacketsBusyForwarder = + metrics.DroppedPacketsTotal.MustCurryWith(ifLabels).MustCurryWith(scLabels).With(reasonMap) + + reasonMap["reason"] = "busy_slow_path" + c.DroppedPacketsBusySlowPath = + metrics.DroppedPacketsTotal.MustCurryWith(ifLabels).MustCurryWith(scLabels).With(reasonMap) + + c.InputBytesTotal.Add(0) + c.InputPacketsTotal.Add(0) + c.DroppedPacketsInvalid.Add(0) + c.DroppedPacketsBusyProcessor.Add(0) + c.DroppedPacketsBusyForwarder.Add(0) + c.DroppedPacketsBusySlowPath.Add(0) + c.ProcessedPackets.Add(0) + return c +} + +func newOutputMetrics( + metrics *Metrics, + ifLabels prometheus.Labels, + scLabels prometheus.Labels, + ttLabels prometheus.Labels) outputMetrics { + + om := outputMetrics{} + om.OutputBytesTotal = + metrics.OutputBytesTotal.MustCurryWith(ifLabels).MustCurryWith(scLabels).With(ttLabels) + om.OutputPacketsTotal = + metrics.OutputPacketsTotal.MustCurryWith(ifLabels).MustCurryWith(scLabels).With(ttLabels) + om.OutputBytesTotal.Add(0) + om.OutputPacketsTotal.Add(0) + return om +} + +func interfaceLabels(id uint16, localIA addr.IA, neighbors map[uint16]addr.IA) prometheus.Labels { + if id == 0 { + return prometheus.Labels{ + "isd_as": localIA.String(), + "interface": "internal", + "neighbor_isd_as": localIA.String(), + } + } + return prometheus.Labels{ + "isd_as": localIA.String(), + "interface": strconv.FormatUint(uint64(id), 10), + "neighbor_isd_as": neighbors[id].String(), + } +} + +func serviceLabels(localIA addr.IA, svc addr.SVC) prometheus.Labels { + return prometheus.Labels{ + "isd_as": localIA.String(), + "service": svc.BaseString(), + } +} diff --git a/tools/topology/monitoring.py b/tools/topology/monitoring.py index 60ac56007..930a7b521 100644 --- a/tools/topology/monitoring.py +++ b/tools/topology/monitoring.py @@ -69,6 +69,9 @@ class MonitoringGenerator(object): "Sciond": "SD", "Dispatcher": "dispatcher", } + JOB_METRIC_RELABEL = { + # "BR": "" + } def __init__(self, args): """ @@ -127,10 +130,14 @@ def _write_config_files(self, config_dict): def _write_config_file(self, config_path, job_dict): scrape_configs = [] for job_name, file_paths in job_dict.items(): - scrape_configs.append({ + job_scrape_config = { 'job_name': job_name, 'file_sd_configs': [{'files': file_paths}], - }) + } + relabels = self.JOB_METRIC_RELABEL.get(job_name) + if relabels is not None: + job_scrape_config['metric_relabel_configs'] = relabels + scrape_configs.append(job_scrape_config) config = { 'global': { 'scrape_interval': '1s', @@ -164,7 +171,7 @@ def _write_dc_file(self): 'version': DOCKER_COMPOSE_CONFIG_VERSION, 'services': { 'prometheus': { - 'image': 'prom/prometheus:v2.6.0', + 'image': 'prom/prometheus:v2.47.2', 'container_name': name+'prometheus', 'network_mode': 'host', 'volumes': [ From ccf98fd8c5f1ca79a3f86d5156fee8f96c013656 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Mon, 30 Oct 2023 21:47:36 +0100 Subject: [PATCH 075/255] build: update Go to 1.21.3 (#4428) --- WORKSPACE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WORKSPACE b/WORKSPACE index 491241f5f..38ab00fe6 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -54,7 +54,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe go_register_toolchains( nogo = "@//:nogo", - version = "1.21.1", + version = "1.21.3", ) # Gazelle From 576fa432582a4de1f2f181329d3a16cbf4570cf8 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Tue, 31 Oct 2023 09:51:44 +0100 Subject: [PATCH 076/255] build: drop @cgrindel_bazel_starlib//updatesrc (#4427) Refactor the remaining targets that depended on @cgrindel_bazel_starlib//updatesrc. The repository has now been completely migrated to @aspect_bazel_lib//lib:write_source_files. During the refactor, we dropped the functionality to write the source files in rules_openapi. Instead, the caller side can decide how to write the source files. This makes the rules more composable and easier to use. The functionality has been moved to a macro in private/mgmtapi/api.bzl, which is used inside of scionproto/scion. --- .bazelignore | 1 + BUILD.bazel | 19 +++++----- Makefile | 1 - WORKSPACE | 6 --- control/mgmtapi/BUILD.bazel | 3 +- daemon/mgmtapi/BUILD.bazel | 3 +- dispatcher/mgmtapi/BUILD.bazel | 3 +- gateway/mgmtapi/BUILD.bazel | 3 +- private/ca/api/BUILD.bazel | 2 +- private/mgmtapi/api.bzl | 48 ++++++++++++++++++++++++ private/mgmtapi/cppki/api/BUILD.bazel | 3 +- private/mgmtapi/health/api/BUILD.bazel | 3 +- private/mgmtapi/segments/api/BUILD.bazel | 3 +- router/mgmtapi/BUILD.bazel | 3 +- rules_openapi/defs.bzl | 41 ++++---------------- rules_openapi/dependencies.bzl | 12 ------ rules_openapi/internal/bundle.bzl | 11 +++++- rules_openapi/internal/generate.bzl | 45 +++++++++++----------- rules_openapi/internal/header.bzl | 45 ---------------------- rules_openapi/internal/header.sh | 12 ------ rules_openapi/rules_starlib.patch | 13 ------- spec/BUILD.bazel | 16 ++++++++ tools/lint/go_embed.bzl | 7 ---- 23 files changed, 128 insertions(+), 175 deletions(-) create mode 100644 private/mgmtapi/api.bzl delete mode 100644 rules_openapi/internal/header.bzl delete mode 100755 rules_openapi/internal/header.sh delete mode 100644 rules_openapi/rules_starlib.patch diff --git a/.bazelignore b/.bazelignore index 19dbe9577..1c4373a08 100644 --- a/.bazelignore +++ b/.bazelignore @@ -1,4 +1,5 @@ bin +doc/_build docker/_build rules_openapi/tools/node_modules tools/lint/logctxcheck/testdata/src diff --git a/BUILD.bazel b/BUILD.bazel index 267914fd4..fcc01787b 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -7,7 +7,6 @@ load("//tools/lint:write_source_files.bzl", "write_source_files") load("//tools/lint/python:flake8_config.bzl", "flake8_lint_config") load("//:nogo.bzl", "nogo_deps") load("@com_github_bazelbuild_buildtools//buildifier:def.bzl", "buildifier") -load("@cgrindel_bazel_starlib//updatesrc:defs.bzl", "updatesrc_update_all") # gazelle:prefix github.com/scionproto/scion # gazelle:map_kind go_library go_library //tools/lint:go.bzl @@ -233,19 +232,21 @@ buildifier( mode = "check", ) -# Runs all update_src targets in this Workspace. Currently, generating the -# OpenAPI specs is the last target that depends on update_src. Eventually, -# this should be transitioned to write_all_source_files below. -updatesrc_update_all( - name = "update_all", -) - # Runs all write_source_files targets in this Workspace. To update the list run # bazel run @com_github_bazelbuild_buildtools//buildozer -- --root_dir $PWD "add additional_update_targets $( bazel query 'filter("^.*[^\d]$", kind(_write_source_file, //...)) except //:write_all_source_files' | tr '\n' ' ')" //:write_all_source_files write_source_files( name = "write_all_source_files", additional_update_targets = [ - "//doc/_build/_static/command:write_files", + "//control/mgmtapi:write_files", + "//daemon/mgmtapi:write_files", + "//dispatcher/mgmtapi:write_files", "//doc/command:write_files", + "//gateway/mgmtapi:write_files", + "//private/ca/api:write_files", + "//private/mgmtapi/cppki/api:write_files", + "//private/mgmtapi/health/api:write_files", + "//private/mgmtapi/segments/api:write_files", + "//router/mgmtapi:write_files", + "//spec:write_files", ], ) diff --git a/Makefile b/Makefile index 2cb241940..e5a3ae226 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,6 @@ antlr: write_all_source_files: bazel run //:write_all_source_files - bazel run //:update_all .PHONY: lint lint-bazel lint-bazel-buildifier lint-doc lint-doc-mdlint lint-go lint-go-bazel lint-go-gazelle lint-go-golangci lint-go-semgrep lint-openapi lint-openapi-spectral lint-protobuf lint-protobuf-buf diff --git a/WORKSPACE b/WORKSPACE index 38ab00fe6..a7e9d2ff2 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -297,9 +297,3 @@ rules_openapi_dependencies() load("//rules_openapi:install.bzl", "rules_openapi_install_yarn_dependencies") rules_openapi_install_yarn_dependencies() - -# TODO(lukedirtwalker): can that be integrated in the rules_openapi_dependencies -# call above somehow? -load("@cgrindel_bazel_starlib//:deps.bzl", "bazel_starlib_dependencies") - -bazel_starlib_dependencies() diff --git a/control/mgmtapi/BUILD.bazel b/control/mgmtapi/BUILD.bazel index 69012989b..c2e82115a 100644 --- a/control/mgmtapi/BUILD.bazel +++ b/control/mgmtapi/BUILD.bazel @@ -1,5 +1,6 @@ load("//tools/lint:go.bzl", "go_library", "go_test") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs", "openapi_generate_go") +load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs") +load("//private/mgmtapi:api.bzl", "openapi_generate_go") openapi_build_docs( name = "doc", diff --git a/daemon/mgmtapi/BUILD.bazel b/daemon/mgmtapi/BUILD.bazel index 33f3f3ca0..e9814e69e 100644 --- a/daemon/mgmtapi/BUILD.bazel +++ b/daemon/mgmtapi/BUILD.bazel @@ -1,5 +1,6 @@ load("//tools/lint:go.bzl", "go_library") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs", "openapi_generate_go") +load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs") +load("//private/mgmtapi:api.bzl", "openapi_generate_go") openapi_build_docs( name = "doc", diff --git a/dispatcher/mgmtapi/BUILD.bazel b/dispatcher/mgmtapi/BUILD.bazel index d63ed1b5d..6fe00d67b 100644 --- a/dispatcher/mgmtapi/BUILD.bazel +++ b/dispatcher/mgmtapi/BUILD.bazel @@ -1,5 +1,6 @@ load("//tools/lint:go.bzl", "go_library") -load("//rules_openapi:defs.bzl", "openapi_build_docs", "openapi_generate_go") +load("//rules_openapi:defs.bzl", "openapi_build_docs") +load("//private/mgmtapi:api.bzl", "openapi_generate_go") openapi_build_docs( name = "doc", diff --git a/gateway/mgmtapi/BUILD.bazel b/gateway/mgmtapi/BUILD.bazel index 22076e129..49e5d6d87 100644 --- a/gateway/mgmtapi/BUILD.bazel +++ b/gateway/mgmtapi/BUILD.bazel @@ -1,5 +1,6 @@ load("//tools/lint:go.bzl", "go_library") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs", "openapi_generate_go") +load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs") +load("//private/mgmtapi:api.bzl", "openapi_generate_go") openapi_build_docs( name = "doc", diff --git a/private/ca/api/BUILD.bazel b/private/ca/api/BUILD.bazel index f23d09bbc..2d1759546 100644 --- a/private/ca/api/BUILD.bazel +++ b/private/ca/api/BUILD.bazel @@ -1,5 +1,5 @@ load("//tools/lint:go.bzl", "go_library") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_generate_go") +load("//private/mgmtapi:api.bzl", "openapi_generate_go") openapi_generate_go( name = "api_generated", diff --git a/private/mgmtapi/api.bzl b/private/mgmtapi/api.bzl new file mode 100644 index 000000000..fb799c0dd --- /dev/null +++ b/private/mgmtapi/api.bzl @@ -0,0 +1,48 @@ +"""OpenAPI Macros +Macros for generating Go code from OpenAPI specs. +""" + +load("//tools/lint:write_source_files.bzl", "write_source_files") +load("//rules_openapi:defs.bzl", _openapi_generate_go = "openapi_generate_go") + +def openapi_generate_go( + name, + client = True, + server = True, + spec = True, + types = True, + **kwargs): + """ + Generates Go code from an OpenAPI spec. + + This macro creates two additional rules: + - {{name}}_files: A filegroup with the generated files. + - write_files: A write_source_files rule that writes the generated files to + the source directory. + + Args: + name: The name of the rule. + client: Whether to generate a client. + server: Whether to generate a server. + spec: Whether to generate a spec. + types: Whether to generate types. + **kwargs: Ad. + """ + + write_files = {} + for typ, gen in {"client": client, "server": server, "spec": spec, "types": types}.items(): + if not gen: + continue + src = typ + ".bzl.gen.go" + kwargs["out_" + typ] = typ + ".bzl.gen.go" + write_files[typ + ".gen.go"] = src + + _openapi_generate_go( + name = name, + **kwargs + ) + + write_source_files( + name = "write_files", + files = write_files, + ) diff --git a/private/mgmtapi/cppki/api/BUILD.bazel b/private/mgmtapi/cppki/api/BUILD.bazel index 01cc4fe91..8e0d5d1f3 100644 --- a/private/mgmtapi/cppki/api/BUILD.bazel +++ b/private/mgmtapi/cppki/api/BUILD.bazel @@ -1,10 +1,9 @@ load("//tools/lint:go.bzl", "go_library", "go_test") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_generate_go") +load("//private/mgmtapi:api.bzl", "openapi_generate_go") openapi_generate_go( name = "api_generated", src = "//spec:cppki", - server = True, spec = False, ) diff --git a/private/mgmtapi/health/api/BUILD.bazel b/private/mgmtapi/health/api/BUILD.bazel index a54713355..da5148b4b 100644 --- a/private/mgmtapi/health/api/BUILD.bazel +++ b/private/mgmtapi/health/api/BUILD.bazel @@ -1,10 +1,9 @@ load("//tools/lint:go.bzl", "go_library") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_generate_go") +load("//private/mgmtapi:api.bzl", "openapi_generate_go") openapi_generate_go( name = "api_generated", src = "//spec:health", - server = True, spec = False, ) diff --git a/private/mgmtapi/segments/api/BUILD.bazel b/private/mgmtapi/segments/api/BUILD.bazel index 37c6e33fd..ef2a43e8d 100644 --- a/private/mgmtapi/segments/api/BUILD.bazel +++ b/private/mgmtapi/segments/api/BUILD.bazel @@ -1,10 +1,9 @@ load("//tools/lint:go.bzl", "go_library", "go_test") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_generate_go") +load("//private/mgmtapi:api.bzl", "openapi_generate_go") openapi_generate_go( name = "api_generated", src = "//spec:segments", - server = True, spec = False, ) diff --git a/router/mgmtapi/BUILD.bazel b/router/mgmtapi/BUILD.bazel index f1d74c2a5..c57c59a4e 100644 --- a/router/mgmtapi/BUILD.bazel +++ b/router/mgmtapi/BUILD.bazel @@ -1,5 +1,6 @@ load("//tools/lint:go.bzl", "go_library", "go_test") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs", "openapi_generate_go") +load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs") +load("//private/mgmtapi:api.bzl", "openapi_generate_go") openapi_build_docs( name = "doc", diff --git a/rules_openapi/defs.bzl b/rules_openapi/defs.bzl index fc537789c..8dfffe5d7 100644 --- a/rules_openapi/defs.bzl +++ b/rules_openapi/defs.bzl @@ -1,8 +1,6 @@ load("//rules_openapi/internal:generate.bzl", _openapi_generate_go = "openapi_generate_go") load("//rules_openapi/internal:bundle.bzl", _openapi_bundle = "openapi_bundle") load("//rules_openapi/internal:docs.bzl", _openapi_build_docs = "openapi_build_docs") -load("//rules_openapi/internal:header.bzl", _header = "header") -load("@cgrindel_bazel_starlib//updatesrc:defs.bzl", "updatesrc_update") def openapi_bundle( name, @@ -10,22 +8,17 @@ def openapi_bundle( entrypoint, visibility = None): _openapi_bundle( - name = name, + name = name + "-no-header", + out = name + "-no-header.bzl.gen.yml", srcs = srcs, entrypoint = entrypoint, - visibility = visibility, - ) - - _header_target = name + "-add-header" - _header( - name = _header_target, - srcs = [":" + name], - header = "# GENERATED FILE DO NOT EDIT", ) - - updatesrc_update( - name = name + "-update", - deps = [":" + _header_target], + native.genrule( + name = name, + srcs = [name + "-no-header"], + outs = [name + ".bzl.gen.yml"], + cmd = "(echo '# GENERATED FILE DO NOT EDIT'; cat $<) > $@", + visibility = visibility, ) def openapi_generate_go( @@ -36,24 +29,6 @@ def openapi_generate_go( **kwargs ) - generate = { - "types": kwargs.get("types", True), - "server": kwargs.get("server", True), - "client": kwargs.get("client", True), - "spec": kwargs.get("spec", True), - } - - srcs = [] - for k, v in generate.items(): - if not v: - continue - srcs.append(k + ".gen.go") - updatesrc_update( - name = name + "-update", - srcs = srcs, - outs = [":" + name], - ) - def openapi_build_docs( name, src, diff --git a/rules_openapi/dependencies.bzl b/rules_openapi/dependencies.bzl index ebb231580..47a02d3b3 100644 --- a/rules_openapi/dependencies.bzl +++ b/rules_openapi/dependencies.bzl @@ -8,15 +8,3 @@ def rules_openapi_dependencies(): sha256 = "b32a4713b45095e9e1921a7fcb1adf584bc05959f3336e7351bcf77f015a2d7c", urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/4.1.0/rules_nodejs-4.1.0.tar.gz"], ) - - maybe( - http_archive, - name = "cgrindel_bazel_starlib", - sha256 = "163a45d949fdb96b328bb44fe56976c610c6728c77118c6cd999f26cedca97eb", - strip_prefix = "bazel-starlib-0.2.1", - urls = [ - "http://github.com/cgrindel/bazel-starlib/archive/v0.2.1.tar.gz", - ], - patches = ["@com_github_scionproto_scion//rules_openapi:rules_starlib.patch"], - patch_args = ["-p1"], - ) diff --git a/rules_openapi/internal/bundle.bzl b/rules_openapi/internal/bundle.bzl index 6021eb1c8..f0bd3e097 100644 --- a/rules_openapi/internal/bundle.bzl +++ b/rules_openapi/internal/bundle.bzl @@ -1,8 +1,11 @@ load("@bazel_skylib//lib:shell.bzl", "shell") def _openapi_bundle_impl(ctx): - prefix = ctx.label.name - out_file = ctx.actions.declare_file(prefix + ".gen.yml") + if ctx.outputs.out: + out_file = ctx.outputs.out + else: + out_file = ctx.actions.declare_file(ctx.label.name + ".bzl.gen.yml") + cmd = "{bin} bundle --output {out} {entrypoint}".format( bin = ctx.executable._openapi_cli.path, out = shell.quote(out_file.path), @@ -29,6 +32,10 @@ openapi_bundle = rule( doc = "All files that are referenced in the entrypoint file", allow_files = [".yml"], ), + "out": attr.output( + doc = "The bundled open API specification file", + mandatory = False, + ), "entrypoint": attr.label( doc = "The main source to generate files from", allow_single_file = [".yml"], diff --git a/rules_openapi/internal/generate.bzl b/rules_openapi/internal/generate.bzl index 4987523d1..8b2cda5f2 100644 --- a/rules_openapi/internal/generate.bzl +++ b/rules_openapi/internal/generate.bzl @@ -2,16 +2,15 @@ load("@bazel_skylib//lib:shell.bzl", "shell") def _openapi_generate_go(ctx): generate = { - "types": ctx.attr.types, - "server": ctx.attr.server, - "client": ctx.attr.client, - "spec": ctx.attr.spec, + "types": ctx.outputs.out_types, + "server": ctx.outputs.out_server, + "client": ctx.outputs.out_client, + "spec": ctx.outputs.out_spec, } out_files = [] - for k, v in generate.items(): - if not v: + for k, out_file in generate.items(): + if not out_file: continue - out_file = ctx.actions.declare_file(k + ".gen.go") generate_kind = k if generate_kind == "server": generate_kind = "chi-server" @@ -69,26 +68,10 @@ openapi_generate_go = rule( doc = "The Go package the generated code should live in.", default = "api", ), - "types": attr.bool( - doc = "Whether the types file should be generated", - default = True, - ), "types_excludes": attr.label( doc = "The file containing the schema list to exclude during the types generation.", allow_single_file = True, ), - "server": attr.bool( - doc = "Whether the server code should be generated", - default = True, - ), - "client": attr.bool( - doc = "Whehter the client code should be generated", - default = True, - ), - "spec": attr.bool( - doc = "Whether the spec code should be generated", - default = True, - ), "templates": attr.label_list( doc = """Folder containing Go templates to be used during code generation. Note that the template file names need to match the ones used by the @@ -102,5 +85,21 @@ openapi_generate_go = rule( executable = True, cfg = "target", ), + "out_types": attr.output( + doc = "The generated types file.", + mandatory = False, + ), + "out_server": attr.output( + doc = "The generated server file.", + mandatory = False, + ), + "out_client": attr.output( + doc = "The generated client file.", + mandatory = False, + ), + "out_spec": attr.output( + doc = "The generated spec file.", + mandatory = False, + ), }, ) diff --git a/rules_openapi/internal/header.bzl b/rules_openapi/internal/header.bzl deleted file mode 100644 index f061dad1e..000000000 --- a/rules_openapi/internal/header.bzl +++ /dev/null @@ -1,45 +0,0 @@ -# This file was copied from https://github.com/cgrindel/rules_updatesrc/tree/main/examples/simple/header -load( - "@cgrindel_bazel_starlib//updatesrc:defs.bzl", - "UpdateSrcsInfo", - "update_srcs", -) - -def _header_impl(ctx): - outs = [] - updsrcs = [] - for src in ctx.files.srcs: - out = ctx.actions.declare_file(src.basename + "_with_header") - outs.append(out) - updsrcs.append(update_srcs.create(src = src, out = out)) - ctx.actions.run( - outputs = [out], - inputs = [src], - executable = ctx.executable._header_tool, - arguments = [src.path, out.path, ctx.attr.header], - ) - - return [ - DefaultInfo(files = depset(outs)), - UpdateSrcsInfo(update_srcs = depset(updsrcs)), - ] - -header = rule( - implementation = _header_impl, - attrs = { - "srcs": attr.label_list( - allow_files = True, - mandatory = True, - ), - "header": attr.string( - mandatory = True, - ), - "_header_tool": attr.label( - default = "@com_github_scionproto_scion//rules_openapi/internal:header.sh", - executable = True, - cfg = "host", - allow_files = True, - ), - }, - doc = "Adds a header to the src files.", -) diff --git a/rules_openapi/internal/header.sh b/rules_openapi/internal/header.sh deleted file mode 100755 index 3ac240d0e..000000000 --- a/rules_openapi/internal/header.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -# This file is copied from https://github.com/cgrindel/rules_updatesrc/blob/main/examples/simple/header/header.sh - -src="$1" -out="$2" -header="$3" - -first_line=$(head -n 1 "${src}") -if [[ "${first_line}" != "${header}" ]]; then - echo "${header}" > "${out}" -fi -cat "${src}" >> "${out}" diff --git a/rules_openapi/rules_starlib.patch b/rules_openapi/rules_starlib.patch deleted file mode 100644 index 3ea25836d..000000000 --- a/rules_openapi/rules_starlib.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/updatesrc/private/updatesrc_update.bzl b/updatesrc/private/updatesrc_update.bzl -index c0cbfc1..a8d24ca 100644 ---- a/updatesrc/private/updatesrc_update.bzl -+++ b/updatesrc/private/updatesrc_update.bzl -@@ -49,7 +49,7 @@ if [[ ! -z "${BUILD_WORKSPACE_DIRECTORY}" ]]; then - cd "${BUILD_WORKSPACE_DIRECTORY}" - fi - """ + "\n".join([ -- "cp -f $(readlink \"${{runfiles_dir}}/{out}\") {src}".format( -+ "cp -f $(readlink \"${{runfiles_dir}}/{out}\") {src}\nchmod 0444 {src}".format( - src = updsrc.src.short_path, - out = updsrc.out.short_path, - ) diff --git a/spec/BUILD.bazel b/spec/BUILD.bazel index 49b6a8e3b..88f9cea64 100644 --- a/spec/BUILD.bazel +++ b/spec/BUILD.bazel @@ -1,4 +1,5 @@ load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_bundle") +load("//tools/lint:write_source_files.bzl", "write_source_files") openapi_bundle( name = "control", @@ -100,3 +101,18 @@ openapi_bundle( entrypoint = "//spec/health:spec.yml", visibility = ["//visibility:public"], ) + +write_source_files( + name = "write_files", + files = { + "control.gen.yml": ":control", + "ca.gen.yml": ":ca", + "dispatcher.gen.yml": ":dispatcher", + "daemon.gen.yml": ":daemon", + "gateway.gen.yml": ":gateway", + "router.gen.yml": ":router", + "segments.gen.yml": ":segments", + "cppki.gen.yml": ":cppki", + "health.gen.yml": ":health", + }, +) diff --git a/tools/lint/go_embed.bzl b/tools/lint/go_embed.bzl index 98e10f8bd..9e47b4ebb 100644 --- a/tools/lint/go_embed.bzl +++ b/tools/lint/go_embed.bzl @@ -1,5 +1,4 @@ load("@io_bazel_rules_go//go:def.bzl", _go_embed_data = "go_embed_data") -load("@cgrindel_bazel_starlib//updatesrc:defs.bzl", "updatesrc_update") load(":go_fmt.bzl", _go_fmt = "go_fmt") def go_embed_data( @@ -22,9 +21,3 @@ def go_embed_data( name = fmt_name, src = ":" + name, ) - - updatesrc_update( - name = name + "-update", - srcs = [out_src], - outs = [":" + fmt_name], - ) From 9ebc8900303bf25d99bf2d996bcf97cad1b4060a Mon Sep 17 00:00:00 2001 From: Lukas Vogel Date: Tue, 31 Oct 2023 13:31:47 +0100 Subject: [PATCH 077/255] deps: update bazel & bazel libs (#4426) Drop the `go_embed_data` custom rules, those were deprecated for a long time. Drop most of the custom `rules_openapi` bazel rules. Users are recommended to use their own invocations of the JS tools. --- .bazelignore | 2 +- .bazelversion | 2 +- BUILD.bazel | 5 + Makefile | 4 +- WORKSPACE | 124 +- control/mgmtapi/BUILD.bazel | 5 +- daemon/mgmtapi/BUILD.bazel | 5 +- dispatcher/mgmtapi/BUILD.bazel | 5 +- gateway/mgmtapi/BUILD.bazel | 5 +- licenses/BUILD.bazel | 2 +- .../third_party/utf8_range}/LICENSE | 22 +- .../third_party/wyhash/LICENSE | 25 - licenses/data/org_golang_x_sys/LICENSE | 0 .../lib/Tix8.4.3/license.terms | 54 - .../lib/python3.10/LICENSE.txt | 279 -- .../pip-22.2.1.dist-info/LICENSE.txt | 20 - .../lib/tk8.6/demos/license.terms | 40 - nogo.json | 7 +- pkg/proto/control_plane/cppki.pb.go | 4 +- pkg/proto/control_plane/drkey.pb.go | 4 +- .../seg_detached_extensions.pb.go | 4 +- pkg/proto/control_plane/renewal.pb.go | 4 +- pkg/proto/control_plane/seg.pb.go | 4 +- pkg/proto/control_plane/seg_extensions.pb.go | 4 +- pkg/proto/control_plane/svc_resolution.pb.go | 4 +- pkg/proto/crypto/signed.pb.go | 4 +- pkg/proto/daemon/daemon.pb.go | 4 +- pkg/proto/discovery/discovery.pb.go | 4 +- pkg/proto/drkey/drkey.pb.go | 4 +- pkg/proto/gateway/control.pb.go | 4 +- pkg/proto/gateway/prefix.pb.go | 4 +- pkg/proto/hidden_segment/hidden_segment.pb.go | 4 +- private/mgmtapi/api.bzl | 62 + private/mgmtapi/tools/BUILD.bazel | 10 + private/mgmtapi/tools/package.json | 30 + private/mgmtapi/tools/pnpm-lock.yaml | 3231 +++++++++++++++++ router/mgmtapi/BUILD.bazel | 5 +- rules_openapi/defs.bzl | 33 - rules_openapi/dependencies.bzl | 10 - rules_openapi/install.bzl | 20 - rules_openapi/internal/BUILD.bazel | 5 - rules_openapi/internal/bundle.bzl | 50 - rules_openapi/internal/docs.bzl | 39 - rules_openapi/tools/BUILD.bazel | 6 - rules_openapi/tools/README.md | 15 - rules_openapi/tools/package.json | 8 - rules_openapi/tools/yarn.lock | 2859 --------------- spec/BUILD.bazel | 65 +- spec/ca/BUILD.bazel | 17 +- spec/common/BUILD.bazel | 8 +- spec/control/BUILD.bazel | 17 +- spec/cppki/BUILD.bazel | 8 +- spec/daemon/BUILD.bazel | 8 +- spec/dispatcher/BUILD.bazel | 8 +- spec/gateway/BUILD.bazel | 8 +- spec/health/BUILD.bazel | 8 +- spec/router/BUILD.bazel | 17 +- spec/segments/BUILD.bazel | 8 +- tools/licenses.sh | 6 +- tools/lint/go.bzl | 3 - tools/lint/go_embed.bzl | 23 - 61 files changed, 3589 insertions(+), 3660 deletions(-) rename licenses/data/{python3_10_x86_64-unknown-linux-gnu/lib/python3.10/site-packages/setuptools-63.2.0.dist-info => com_google_protobuf/third_party/utf8_range}/LICENSE (58%) delete mode 100644 licenses/data/com_google_protobuf/third_party/wyhash/LICENSE mode change 100644 => 100755 licenses/data/org_golang_x_sys/LICENSE delete mode 100644 licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/Tix8.4.3/license.terms delete mode 100644 licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/LICENSE.txt delete mode 100644 licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/site-packages/pip-22.2.1.dist-info/LICENSE.txt delete mode 100644 licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/tk8.6/demos/license.terms create mode 100644 private/mgmtapi/tools/BUILD.bazel create mode 100644 private/mgmtapi/tools/package.json create mode 100644 private/mgmtapi/tools/pnpm-lock.yaml delete mode 100644 rules_openapi/dependencies.bzl delete mode 100644 rules_openapi/install.bzl delete mode 100644 rules_openapi/internal/bundle.bzl delete mode 100644 rules_openapi/internal/docs.bzl delete mode 100644 rules_openapi/tools/BUILD.bazel delete mode 100644 rules_openapi/tools/README.md delete mode 100644 rules_openapi/tools/package.json delete mode 100644 rules_openapi/tools/yarn.lock delete mode 100644 tools/lint/go_embed.bzl diff --git a/.bazelignore b/.bazelignore index 1c4373a08..26c872b96 100644 --- a/.bazelignore +++ b/.bazelignore @@ -1,5 +1,5 @@ bin doc/_build docker/_build -rules_openapi/tools/node_modules +private/mgmtapi/tools/node_modules tools/lint/logctxcheck/testdata/src diff --git a/.bazelversion b/.bazelversion index 8a30e8f94..19b860c18 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -5.4.0 +6.4.0 diff --git a/BUILD.bazel b/BUILD.bazel index fcc01787b..17a531069 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -7,6 +7,7 @@ load("//tools/lint:write_source_files.bzl", "write_source_files") load("//tools/lint/python:flake8_config.bzl", "flake8_lint_config") load("//:nogo.bzl", "nogo_deps") load("@com_github_bazelbuild_buildtools//buildifier:def.bzl", "buildifier") +load("@npm//private/mgmtapi/tools:@stoplight/spectral-cli/package_json.bzl", spectral_bin = "bin") # gazelle:prefix github.com/scionproto/scion # gazelle:map_kind go_library go_library //tools/lint:go.bzl @@ -232,6 +233,10 @@ buildifier( mode = "check", ) +spectral_bin.spectral_binary( + name = "spectral", +) + # Runs all write_source_files targets in this Workspace. To update the list run # bazel run @com_github_bazelbuild_buildtools//buildozer -- --root_dir $PWD "add additional_update_targets $( bazel query 'filter("^.*[^\d]$", kind(_write_source_file, //...)) except //:write_all_source_files' | tr '\n' ' ')" //:write_all_source_files write_source_files( diff --git a/Makefile b/Makefile index e5a3ae226..fc555c7e0 100644 --- a/Makefile +++ b/Makefile @@ -122,11 +122,11 @@ lint-openapi: lint-openapi-spectral lint-openapi-spectral: $(info ==> $@) - @tools/quiet bazel run --config=quiet @rules_openapi_npm//@stoplight/spectral-cli/bin:spectral -- lint --ruleset ${PWD}/spec/.spectral.yml ${PWD}/spec/*.gen.yml + @tools/quiet bazel run --config=quiet //:spectral -- lint --ruleset ${PWD}/spec/.spectral.yml ${PWD}/spec/*.gen.yml lint-doc: lint-doc-mdlint lint-doc-mdlint: $(info ==> $@) - @FILES=$$(find -type f -iname '*.md' -not -path "./rules_openapi/tools/node_modules/*" -not -path "./.github/**/*" | grep -vf tools/md/skipped); \ + @FILES=$$(find -type f -iname '*.md' -not -path "./private/mgmtapi/tools/node_modules/*" -not -path "./.github/**/*" | grep -vf tools/md/skipped); \ docker run --rm -v ${PWD}:/data -v ${PWD}/tools/md/mdlintstyle.rb:/style.rb $$(docker build -q tools/md) $${FILES} -s /style.rb diff --git a/WORKSPACE b/WORKSPACE index a7e9d2ff2..e0c3552cf 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,8 +1,5 @@ workspace( name = "com_github_scionproto_scion", - managed_directories = { - "@rules_openapi_npm": ["rules_openapi/tools/node_modules"], - }, ) load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") @@ -31,22 +28,28 @@ lint_setup({ http_archive( name = "aspect_bazel_lib", - sha256 = "e3151d87910f69cf1fc88755392d7c878034a69d6499b287bcfc00b1cf9bb415", - strip_prefix = "bazel-lib-1.32.1", - url = "https://github.com/aspect-build/bazel-lib/archive/refs/tags/v1.32.1.tar.gz", + sha256 = "a185ccff9c1b8589c63f66d7eb908de15c5d6bb05562be5f46336c53e7a7326a", + strip_prefix = "bazel-lib-2.0.0-rc1", + url = "https://github.com/aspect-build/bazel-lib/releases/download/v2.0.0-rc1/bazel-lib-v2.0.0-rc1.tar.gz", ) -load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies") +load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "aspect_bazel_lib_register_toolchains") + +# Required bazel-lib dependencies aspect_bazel_lib_dependencies() +# Register bazel-lib toolchains + +aspect_bazel_lib_register_toolchains() + # Bazel rules for Golang http_archive( name = "io_bazel_rules_go", - sha256 = "278b7ff5a826f3dc10f04feaf0b70d48b68748ccd512d7f98bf442077f043fe3", + sha256 = "91585017debb61982f7054c9688857a2ad1fd823fc3f9cb05048b0025c47d023", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.41.0/rules_go-v0.41.0.zip", - "https://github.com/bazelbuild/rules_go/releases/download/v0.41.0/rules_go-v0.41.0.zip", + "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.42.0/rules_go-v0.42.0.zip", + "https://github.com/bazelbuild/rules_go/releases/download/v0.42.0/rules_go-v0.42.0.zip", ], ) @@ -60,28 +63,14 @@ go_register_toolchains( # Gazelle http_archive( name = "bazel_gazelle", - sha256 = "29218f8e0cebe583643cbf93cae6f971be8a2484cdcfa1e45057658df8d54002", + sha256 = "d3fa66a39028e97d76f9e2db8f1b0c11c099e8e01bf363a923074784e451f809", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.32.0/bazel-gazelle-v0.32.0.tar.gz", - "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.32.0/bazel-gazelle-v0.32.0.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.33.0/bazel-gazelle-v0.33.0.tar.gz", + "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.33.0/bazel-gazelle-v0.33.0.tar.gz", ], ) -load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository") - -# Explictly override golang.org/x/sys. Our github.com/quic-go/quic-go cannot -# compile without at least golang.org/x/sys@v0.2.0. The rules_go version that -# we use (v0.34.0) imports an older version. A recent enough version was only introduced -# in v0.36.0. See: https://github.com/bazelbuild/rules_go/commit/64b9226a3bca997866b8831889ffb9de87405a0d -# -# This version should be kept in sync with the go_deps.bzl file. We can remove it -# once we update the rules_go version. -go_repository( - name = "org_golang_x_sys", - importpath = "golang.org/x/sys", - sum = "h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=", - version = "v0.8.0", -) +load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") go_rules_dependencies() @@ -94,26 +83,20 @@ load("//:go_deps.bzl", "go_deps") go_deps() -## Explictly override xerrors: https://github.com/bazelbuild/bazel-gazelle/issues/1217 -# go_repository( -# name = "org_golang_x_xerrors", -# importpath = "golang.org/x/xerrors", -# sum = "h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=", -# version = "v0.0.0-20220907171357-04be3eba64a2", -# ) - gazelle_dependencies() # XXX Needs to be before rules_docker # Python rules http_archive( name = "rules_python", - sha256 = "8c8fe44ef0a9afc256d1e75ad5f448bb59b81aba149b8958f02f7b3a98f5d9b4", - strip_prefix = "rules_python-0.13.0", - url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.13.0.tar.gz", + sha256 = "9d04041ac92a0985e344235f5d946f71ac543f1b1565f2cdbc9a2aaee8adf55b", + strip_prefix = "rules_python-0.26.0", + url = "https://github.com/bazelbuild/rules_python/releases/download/0.26.0/rules_python-0.26.0.tar.gz", ) -load("@rules_python//python:repositories.bzl", "python_register_toolchains") +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") + +py_repositories() python_register_toolchains( name = "python3_10", @@ -131,10 +114,10 @@ install_python_deps() http_archive( name = "rules_pkg", - sha256 = "62eeb544ff1ef41d786e329e1536c1d541bb9bcad27ae984d57f18f314018e66", + sha256 = "8f9ee2dc10c1ae514ee599a8b42ed99fa262b757058f65ad3c384289ff70c4b8", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.6.0/rules_pkg-0.6.0.tar.gz", - "https://github.com/bazelbuild/rules_pkg/releases/download/0.6.0/rules_pkg-0.6.0.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.9.1/rules_pkg-0.9.1.tar.gz", + "https://github.com/bazelbuild/rules_pkg/releases/download/0.9.1/rules_pkg-0.9.1.tar.gz", ], ) @@ -158,9 +141,8 @@ rules_antlr_dependencies("4.9.3") http_archive( name = "io_bazel_rules_docker", - sha256 = "85ffff62a4c22a74dbd98d05da6cf40f497344b3dbf1e1ab0a37ab2a1a6ca014", - strip_prefix = "rules_docker-0.23.0", - urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.23.0/rules_docker-v0.23.0.tar.gz"], + sha256 = "b1e80761a8a8243d03ebca8845e9cc1ba6c82ce7c5179ce2b295cd36f7e394bf", + urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.25.0/rules_docker-v0.25.0.tar.gz"], ) load("@io_bazel_rules_docker//repositories:repositories.bzl", container_repositories = "repositories") @@ -241,9 +223,9 @@ container_pull( # protobuf/gRPC http_archive( name = "rules_proto_grpc", - sha256 = "7954abbb6898830cd10ac9714fbcacf092299fda00ed2baf781172f545120419", - strip_prefix = "rules_proto_grpc-3.1.1", - urls = ["https://github.com/rules-proto-grpc/rules_proto_grpc/archive/3.1.1.tar.gz"], + sha256 = "9ba7299c5eb6ec45b6b9a0ceb9916d0ab96789ac8218269322f0124c0c0d24e2", + strip_prefix = "rules_proto_grpc-4.5.0", + urls = ["https://github.com/rules-proto-grpc/rules_proto_grpc/releases/download/4.5.0/rules_proto_grpc-4.5.0.tar.gz"], ) load("@rules_proto_grpc//:repositories.bzl", "rules_proto_grpc_repos", "rules_proto_grpc_toolchains") @@ -258,18 +240,16 @@ rules_proto_dependencies() rules_proto_toolchains() -load("@rules_proto_grpc//python:repositories.bzl", rules_proto_grpc_python_repos = "python_repos") - -rules_proto_grpc_python_repos() +load("@rules_proto_grpc//buf:repositories.bzl", rules_proto_grpc_buf_repos = "buf_repos") -load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") - -grpc_deps() +rules_proto_grpc_buf_repos() http_archive( name = "com_github_bazelbuild_buildtools", - strip_prefix = "buildtools-master", - url = "https://github.com/bazelbuild/buildtools/archive/2.2.1.zip", + strip_prefix = "buildtools-6.3.3", + urls = [ + "https://github.com/bazelbuild/buildtools/archive/refs/tags/6.3.3.tar.gz", + ], ) http_file( @@ -290,10 +270,32 @@ load("@com_github_scionproto_scion_python_lint_deps//:requirements.bzl", install install_python_lint_deps() -load("//rules_openapi:dependencies.bzl", "rules_openapi_dependencies") +http_archive( + name = "aspect_rules_js", + sha256 = "a949d56fed8fa0a8dd82a0a660acc949253a05b2b0c52a07e4034e27f11218f6", + strip_prefix = "rules_js-1.33.1", + url = "https://github.com/aspect-build/rules_js/releases/download/v1.33.1/rules_js-v1.33.1.tar.gz", +) + +load("@aspect_rules_js//js:repositories.bzl", "rules_js_dependencies") + +rules_js_dependencies() -rules_openapi_dependencies() +load("@rules_nodejs//nodejs:repositories.bzl", "DEFAULT_NODE_VERSION", "nodejs_register_toolchains") + +nodejs_register_toolchains( + name = "nodejs", + node_version = DEFAULT_NODE_VERSION, +) + +load("@aspect_rules_js//npm:npm_import.bzl", "npm_translate_lock") + +npm_translate_lock( + name = "npm", + pnpm_lock = "@com_github_scionproto_scion//private/mgmtapi/tools:pnpm-lock.yaml", + verify_node_modules_ignored = "@com_github_scionproto_scion//:.bazelignore", +) -load("//rules_openapi:install.bzl", "rules_openapi_install_yarn_dependencies") +load("@npm//:repositories.bzl", "npm_repositories") -rules_openapi_install_yarn_dependencies() +npm_repositories() diff --git a/control/mgmtapi/BUILD.bazel b/control/mgmtapi/BUILD.bazel index c2e82115a..20d657d1e 100644 --- a/control/mgmtapi/BUILD.bazel +++ b/control/mgmtapi/BUILD.bazel @@ -1,8 +1,7 @@ load("//tools/lint:go.bzl", "go_library", "go_test") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs") -load("//private/mgmtapi:api.bzl", "openapi_generate_go") +load("//private/mgmtapi:api.bzl", "openapi_docs", "openapi_generate_go") -openapi_build_docs( +openapi_docs( name = "doc", src = "//spec:control", out = "index.html", diff --git a/daemon/mgmtapi/BUILD.bazel b/daemon/mgmtapi/BUILD.bazel index e9814e69e..7d20b0599 100644 --- a/daemon/mgmtapi/BUILD.bazel +++ b/daemon/mgmtapi/BUILD.bazel @@ -1,8 +1,7 @@ load("//tools/lint:go.bzl", "go_library") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs") -load("//private/mgmtapi:api.bzl", "openapi_generate_go") +load("//private/mgmtapi:api.bzl", "openapi_docs", "openapi_generate_go") -openapi_build_docs( +openapi_docs( name = "doc", src = "//spec:daemon", out = "index.html", diff --git a/dispatcher/mgmtapi/BUILD.bazel b/dispatcher/mgmtapi/BUILD.bazel index 6fe00d67b..5bc94f0d3 100644 --- a/dispatcher/mgmtapi/BUILD.bazel +++ b/dispatcher/mgmtapi/BUILD.bazel @@ -1,8 +1,7 @@ load("//tools/lint:go.bzl", "go_library") -load("//rules_openapi:defs.bzl", "openapi_build_docs") -load("//private/mgmtapi:api.bzl", "openapi_generate_go") +load("//private/mgmtapi:api.bzl", "openapi_docs", "openapi_generate_go") -openapi_build_docs( +openapi_docs( name = "doc", src = "//spec:dispatcher", out = "index.html", diff --git a/gateway/mgmtapi/BUILD.bazel b/gateway/mgmtapi/BUILD.bazel index 49e5d6d87..ecf7d7a5c 100644 --- a/gateway/mgmtapi/BUILD.bazel +++ b/gateway/mgmtapi/BUILD.bazel @@ -1,8 +1,7 @@ load("//tools/lint:go.bzl", "go_library") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs") -load("//private/mgmtapi:api.bzl", "openapi_generate_go") +load("//private/mgmtapi:api.bzl", "openapi_docs", "openapi_generate_go") -openapi_build_docs( +openapi_docs( name = "doc", src = "//spec:gateway", out = "index.html", diff --git a/licenses/BUILD.bazel b/licenses/BUILD.bazel index 8fb10c02f..b2c6872cc 100644 --- a/licenses/BUILD.bazel +++ b/licenses/BUILD.bazel @@ -2,7 +2,7 @@ load("@rules_pkg//:pkg.bzl", "pkg_tar") pkg_tar( name = "licenses", - srcs = ["data"], + srcs = glob(["data/**/*"]), package_dir = "/licenses", strip_prefix = "data", visibility = ["//visibility:public"], diff --git a/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/site-packages/setuptools-63.2.0.dist-info/LICENSE b/licenses/data/com_google_protobuf/third_party/utf8_range/LICENSE similarity index 58% rename from licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/site-packages/setuptools-63.2.0.dist-info/LICENSE rename to licenses/data/com_google_protobuf/third_party/utf8_range/LICENSE index 353924be0..c1f087ecc 100644 --- a/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/site-packages/setuptools-63.2.0.dist-info/LICENSE +++ b/licenses/data/com_google_protobuf/third_party/utf8_range/LICENSE @@ -1,19 +1,21 @@ -Copyright Jason R. Coombs +MIT License + +Copyright (c) 2019 Yibo Cai Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/licenses/data/com_google_protobuf/third_party/wyhash/LICENSE b/licenses/data/com_google_protobuf/third_party/wyhash/LICENSE deleted file mode 100644 index 471f09f4c..000000000 --- a/licenses/data/com_google_protobuf/third_party/wyhash/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -For more information, please refer to - diff --git a/licenses/data/org_golang_x_sys/LICENSE b/licenses/data/org_golang_x_sys/LICENSE old mode 100644 new mode 100755 diff --git a/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/Tix8.4.3/license.terms b/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/Tix8.4.3/license.terms deleted file mode 100644 index e48f78f6b..000000000 --- a/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/Tix8.4.3/license.terms +++ /dev/null @@ -1,54 +0,0 @@ -Copyright (c) 1993-1999 Ioi Kim Lam. -Copyright (c) 2000-2001 Tix Project Group. -Copyright (c) 2004 ActiveState - -This software is copyrighted by the above entities -and other parties. The following terms apply to all files associated -with the software unless explicitly disclaimed in individual files. - -The authors hereby grant permission to use, copy, modify, distribute, -and license this software and its documentation for any purpose, provided -that existing copyright notices are retained in all copies and that this -notice is included verbatim in any distributions. No written agreement, -license, or royalty fee is required for any of the authorized uses. -Modifications to this software may be copyrighted by their authors -and need not follow the licensing terms described here, provided that -the new terms are clearly indicated on the first page of each file where -they apply. - -IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY -FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY -DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE -IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE -NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR -MODIFICATIONS. - -GOVERNMENT USE: If you are acquiring this software on behalf of the -U.S. government, the Government shall have only "Restricted Rights" -in the software and related documentation as defined in the Federal -Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you -are acquiring the software on behalf of the Department of Defense, the -software shall be classified as "Commercial Computer Software" and the -Government shall have only "Restricted Rights" as defined in Clause -252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the -authors grant the U.S. Government and others acting in its behalf -permission to use and distribute the software in accordance with the -terms specified in this license. - ----------------------------------------------------------------------- - -Parts of this software are based on the Tcl/Tk software copyrighted by -the Regents of the University of California, Sun Microsystems, Inc., -and other parties. The original license terms of the Tcl/Tk software -distribution is included in the file docs/license.tcltk. - -Parts of this software are based on the HTML Library software -copyrighted by Sun Microsystems, Inc. The original license terms of -the HTML Library software distribution is included in the file -docs/license.html_lib. diff --git a/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/LICENSE.txt b/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/LICENSE.txt deleted file mode 100644 index 02a5145f0..000000000 --- a/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/LICENSE.txt +++ /dev/null @@ -1,279 +0,0 @@ -A. HISTORY OF THE SOFTWARE -========================== - -Python was created in the early 1990s by Guido van Rossum at Stichting -Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands -as a successor of a language called ABC. Guido remains Python's -principal author, although it includes many contributions from others. - -In 1995, Guido continued his work on Python at the Corporation for -National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) -in Reston, Virginia where he released several versions of the -software. - -In May 2000, Guido and the Python core development team moved to -BeOpen.com to form the BeOpen PythonLabs team. In October of the same -year, the PythonLabs team moved to Digital Creations, which became -Zope Corporation. In 2001, the Python Software Foundation (PSF, see -https://www.python.org/psf/) was formed, a non-profit organization -created specifically to own Python-related Intellectual Property. -Zope Corporation was a sponsoring member of the PSF. - -All Python releases are Open Source (see http://www.opensource.org for -the Open Source Definition). Historically, most, but not all, Python -releases have also been GPL-compatible; the table below summarizes -the various releases. - - Release Derived Year Owner GPL- - from compatible? (1) - - 0.9.0 thru 1.2 1991-1995 CWI yes - 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes - 1.6 1.5.2 2000 CNRI no - 2.0 1.6 2000 BeOpen.com no - 1.6.1 1.6 2001 CNRI yes (2) - 2.1 2.0+1.6.1 2001 PSF no - 2.0.1 2.0+1.6.1 2001 PSF yes - 2.1.1 2.1+2.0.1 2001 PSF yes - 2.1.2 2.1.1 2002 PSF yes - 2.1.3 2.1.2 2002 PSF yes - 2.2 and above 2.1.1 2001-now PSF yes - -Footnotes: - -(1) GPL-compatible doesn't mean that we're distributing Python under - the GPL. All Python licenses, unlike the GPL, let you distribute - a modified version without making your changes open source. The - GPL-compatible licenses make it possible to combine Python with - other software that is released under the GPL; the others don't. - -(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, - because its license has a choice of law clause. According to - CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 - is "not incompatible" with the GPL. - -Thanks to the many outside volunteers who have worked under Guido's -direction to make these releases possible. - - -B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON -=============================================================== - -Python software and documentation are licensed under the -Python Software Foundation License Version 2. - -Starting with Python 3.8.6, examples, recipes, and other code in -the documentation are dual licensed under the PSF License Version 2 -and the Zero-Clause BSD license. - -Some software incorporated into Python is under different licenses. -The licenses are listed with code falling under that license. - - -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby -grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, -analyze, test, perform and/or display publicly, prepare derivative works, -distribute, and otherwise use Python alone or in any derivative version, -provided, however, that PSF's License Agreement and PSF's notice of copyright, -i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Python Software Foundation; -All Rights Reserved" are retained in Python alone or in any derivative version -prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 -------------------------------------------- - -BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 - -1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an -office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the -Individual or Organization ("Licensee") accessing and otherwise using -this software in source or binary form and its associated -documentation ("the Software"). - -2. Subject to the terms and conditions of this BeOpen Python License -Agreement, BeOpen hereby grants Licensee a non-exclusive, -royalty-free, world-wide license to reproduce, analyze, test, perform -and/or display publicly, prepare derivative works, distribute, and -otherwise use the Software alone or in any derivative version, -provided, however, that the BeOpen Python License is retained in the -Software, alone or in any derivative version prepared by Licensee. - -3. BeOpen is making the Software available to Licensee on an "AS IS" -basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE -SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS -AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY -DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -5. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -6. This License Agreement shall be governed by and interpreted in all -respects by the law of the State of California, excluding conflict of -law provisions. Nothing in this License Agreement shall be deemed to -create any relationship of agency, partnership, or joint venture -between BeOpen and Licensee. This License Agreement does not grant -permission to use BeOpen trademarks or trade names in a trademark -sense to endorse or promote products or services of Licensee, or any -third party. As an exception, the "BeOpen Python" logos available at -http://www.pythonlabs.com/logos.html may be used according to the -permissions granted on that web page. - -7. By copying, installing or otherwise using the software, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 ---------------------------------------- - -1. This LICENSE AGREEMENT is between the Corporation for National -Research Initiatives, having an office at 1895 Preston White Drive, -Reston, VA 20191 ("CNRI"), and the Individual or Organization -("Licensee") accessing and otherwise using Python 1.6.1 software in -source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, CNRI -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python 1.6.1 -alone or in any derivative version, provided, however, that CNRI's -License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) -1995-2001 Corporation for National Research Initiatives; All Rights -Reserved" are retained in Python 1.6.1 alone or in any derivative -version prepared by Licensee. Alternately, in lieu of CNRI's License -Agreement, Licensee may substitute the following text (omitting the -quotes): "Python 1.6.1 is made available subject to the terms and -conditions in CNRI's License Agreement. This Agreement together with -Python 1.6.1 may be located on the internet using the following -unique, persistent identifier (known as a handle): 1895.22/1013. This -Agreement may also be obtained from a proxy server on the internet -using the following URL: http://hdl.handle.net/1895.22/1013". - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python 1.6.1 or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python 1.6.1. - -4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" -basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. This License Agreement shall be governed by the federal -intellectual property law of the United States, including without -limitation the federal copyright law, and, to the extent such -U.S. federal law does not apply, by the law of the Commonwealth of -Virginia, excluding Virginia's conflict of law provisions. -Notwithstanding the foregoing, with regard to derivative works based -on Python 1.6.1 that incorporate non-separable material that was -previously distributed under the GNU General Public License (GPL), the -law of the Commonwealth of Virginia shall govern this License -Agreement only as to issues arising under or with respect to -Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this -License Agreement shall be deemed to create any relationship of -agency, partnership, or joint venture between CNRI and Licensee. This -License Agreement does not grant permission to use CNRI trademarks or -trade name in a trademark sense to endorse or promote products or -services of Licensee, or any third party. - -8. By clicking on the "ACCEPT" button where indicated, or by copying, -installing or otherwise using Python 1.6.1, Licensee agrees to be -bound by the terms and conditions of this License Agreement. - - ACCEPT - - -CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 --------------------------------------------------- - -Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, -The Netherlands. All rights reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION ----------------------------------------------------------------------- - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. diff --git a/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/site-packages/pip-22.2.1.dist-info/LICENSE.txt b/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/site-packages/pip-22.2.1.dist-info/LICENSE.txt deleted file mode 100644 index 8e7b65eaf..000000000 --- a/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/python3.10/site-packages/pip-22.2.1.dist-info/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008-present The pip developers (see AUTHORS.txt file) - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/tk8.6/demos/license.terms b/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/tk8.6/demos/license.terms deleted file mode 100644 index 01264352c..000000000 --- a/licenses/data/python3_10_x86_64-unknown-linux-gnu/lib/tk8.6/demos/license.terms +++ /dev/null @@ -1,40 +0,0 @@ -This software is copyrighted by the Regents of the University of -California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState -Corporation, Apple Inc. and other parties. The following terms apply to -all files associated with the software unless explicitly disclaimed in -individual files. - -The authors hereby grant permission to use, copy, modify, distribute, -and license this software and its documentation for any purpose, provided -that existing copyright notices are retained in all copies and that this -notice is included verbatim in any distributions. No written agreement, -license, or royalty fee is required for any of the authorized uses. -Modifications to this software may be copyrighted by their authors -and need not follow the licensing terms described here, provided that -the new terms are clearly indicated on the first page of each file where -they apply. - -IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY -FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY -DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE -IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE -NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR -MODIFICATIONS. - -GOVERNMENT USE: If you are acquiring this software on behalf of the -U.S. government, the Government shall have only "Restricted Rights" -in the software and related documentation as defined in the Federal -Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you -are acquiring the software on behalf of the Department of Defense, the -software shall be classified as "Commercial Computer Software" and the -Government shall have only "Restricted Rights" as defined in Clause -252.227-7013 (b) (3) of DFARs. Notwithstanding the foregoing, the -authors grant the U.S. Government and others acting in its behalf -permission to use and distribute the software in accordance with the -terms specified in this license. diff --git a/nogo.json b/nogo.json index bad20152f..924de87ac 100644 --- a/nogo.json +++ b/nogo.json @@ -155,7 +155,9 @@ "gazelle/language/go/gen_std_package_list": "", "gazelle/language/proto/gen/gen_known_imports": "", "gazelle/cmd/gazelle/gazelle": "", - "/com_github_bazelbuild_buildtools": "" + "/com_github_bazelbuild_buildtools": "", + "/io_bazel_rules_docker/": "", + "/com_github_oncilla_ineffassign/": "" } }, "reflectvaluecompare": { @@ -212,7 +214,8 @@ "com_github_vishvananda_netlink/nl": "", "com_github_deepmap_oapi_codegen/pkg/codegen": "", "com_github_quic_go_quic_go": "", - "com_github_bazelbuild_buildtools": "" + "com_github_bazelbuild_buildtools": "", + "/bazel_gazelle/": "" } } } diff --git a/pkg/proto/control_plane/cppki.pb.go b/pkg/proto/control_plane/cppki.pb.go index 6f56be0c2..6eeeb4a9d 100644 --- a/pkg/proto/control_plane/cppki.pb.go +++ b/pkg/proto/control_plane/cppki.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/control_plane/v1/cppki.proto package control_plane diff --git a/pkg/proto/control_plane/drkey.pb.go b/pkg/proto/control_plane/drkey.pb.go index 594607898..fc0516ab5 100644 --- a/pkg/proto/control_plane/drkey.pb.go +++ b/pkg/proto/control_plane/drkey.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/control_plane/v1/drkey.proto package control_plane diff --git a/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go b/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go index 0f5c3051d..da4342be2 100755 --- a/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go +++ b/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/control_plane/experimental/v1/seg_detached_extensions.proto package experimental diff --git a/pkg/proto/control_plane/renewal.pb.go b/pkg/proto/control_plane/renewal.pb.go index ed3359b4c..6ed423068 100644 --- a/pkg/proto/control_plane/renewal.pb.go +++ b/pkg/proto/control_plane/renewal.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/control_plane/v1/renewal.proto package control_plane diff --git a/pkg/proto/control_plane/seg.pb.go b/pkg/proto/control_plane/seg.pb.go index 36f549223..7355fd77d 100644 --- a/pkg/proto/control_plane/seg.pb.go +++ b/pkg/proto/control_plane/seg.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/control_plane/v1/seg.proto package control_plane diff --git a/pkg/proto/control_plane/seg_extensions.pb.go b/pkg/proto/control_plane/seg_extensions.pb.go index 565f0e5bd..f072070bf 100644 --- a/pkg/proto/control_plane/seg_extensions.pb.go +++ b/pkg/proto/control_plane/seg_extensions.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/control_plane/v1/seg_extensions.proto package control_plane diff --git a/pkg/proto/control_plane/svc_resolution.pb.go b/pkg/proto/control_plane/svc_resolution.pb.go index 781251817..3c83185bd 100644 --- a/pkg/proto/control_plane/svc_resolution.pb.go +++ b/pkg/proto/control_plane/svc_resolution.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/control_plane/v1/svc_resolution.proto package control_plane diff --git a/pkg/proto/crypto/signed.pb.go b/pkg/proto/crypto/signed.pb.go index bc09b3824..f094495b1 100644 --- a/pkg/proto/crypto/signed.pb.go +++ b/pkg/proto/crypto/signed.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/crypto/v1/signed.proto package crypto diff --git a/pkg/proto/daemon/daemon.pb.go b/pkg/proto/daemon/daemon.pb.go index 24bddc037..93b3b19c6 100644 --- a/pkg/proto/daemon/daemon.pb.go +++ b/pkg/proto/daemon/daemon.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/daemon/v1/daemon.proto package daemon diff --git a/pkg/proto/discovery/discovery.pb.go b/pkg/proto/discovery/discovery.pb.go index 704dab49b..edc503dbf 100644 --- a/pkg/proto/discovery/discovery.pb.go +++ b/pkg/proto/discovery/discovery.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/discovery/v1/discovery.proto package discovery diff --git a/pkg/proto/drkey/drkey.pb.go b/pkg/proto/drkey/drkey.pb.go index 0c7bc5ebf..3b31cb730 100644 --- a/pkg/proto/drkey/drkey.pb.go +++ b/pkg/proto/drkey/drkey.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/drkey/v1/drkey.proto package drkey diff --git a/pkg/proto/gateway/control.pb.go b/pkg/proto/gateway/control.pb.go index 952a5a067..b7178c3d4 100644 --- a/pkg/proto/gateway/control.pb.go +++ b/pkg/proto/gateway/control.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/gateway/v1/control.proto package gateway diff --git a/pkg/proto/gateway/prefix.pb.go b/pkg/proto/gateway/prefix.pb.go index ce4a8d0e7..a38986ea4 100644 --- a/pkg/proto/gateway/prefix.pb.go +++ b/pkg/proto/gateway/prefix.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/gateway/v1/prefix.proto package gateway diff --git a/pkg/proto/hidden_segment/hidden_segment.pb.go b/pkg/proto/hidden_segment/hidden_segment.pb.go index 5303dc9df..c778eadbe 100644 --- a/pkg/proto/hidden_segment/hidden_segment.pb.go +++ b/pkg/proto/hidden_segment/hidden_segment.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 -// protoc v3.15.3 +// protoc-gen-go v1.31.0 +// protoc v3.21.10 // source: proto/hidden_segment/v1/hidden_segment.proto package hidden_segment diff --git a/private/mgmtapi/api.bzl b/private/mgmtapi/api.bzl index fb799c0dd..51872d095 100644 --- a/private/mgmtapi/api.bzl +++ b/private/mgmtapi/api.bzl @@ -4,6 +4,68 @@ Macros for generating Go code from OpenAPI specs. load("//tools/lint:write_source_files.bzl", "write_source_files") load("//rules_openapi:defs.bzl", _openapi_generate_go = "openapi_generate_go") +load("@npm//private/mgmtapi/tools:@redocly/cli/package_json.bzl", redocly_bin = "bin") + +def openapi_docs( + name, + src, + out, + **kwargs): + """ + Generates HTML documentation from an OpenAPI spec. + + Args: + name: The name of the rule. + src: The source spec file (yml). + out: The output HTML file. + **kwargs: Additional arguments to pass to openapi binary. + """ + + redocly_bin.openapi( + name = name, + srcs = [src], + outs = [out], + args = ["build-docs", "--output", "../../../$@", "../../../$(location {})".format(src)], + **kwargs + ) + +def openapi_bundle( + name, + entrypoint, + visibility = None, + srcs = [], + **kwargs): + """ + Generates a resolved spec file from a set of OpenAPI spec files. + + The file output will be under {{name}}.bzl.gen.yml. + + Args: + name: The name of the rules. + entrypoint: The entrypoint spec file. + visibility: The visibility of the target. + srcs: The list of spec files to bundle. + **kwargs: Additional arguments to pass to openapi binary. (should be srcs) + """ + redocly_bin.openapi( + name = name + "-no-header", + outs = [name + "-no-header.bzl.gen.yml"], + srcs = srcs + [entrypoint], + args = [ + "bundle", + "--output", + "../../../$@", + "../../../$(location {})".format(entrypoint), + ], + **kwargs + ) + native.genrule( + name = name, + srcs = [name + "-no-header"], + outs = [name + ".bzl.gen.yml"], + cmd = "(echo '# GENERATED FILE DO NOT EDIT'; cat $<) > $@", + visibility = visibility, + ) def openapi_generate_go( name, diff --git a/private/mgmtapi/tools/BUILD.bazel b/private/mgmtapi/tools/BUILD.bazel new file mode 100644 index 000000000..30df5b1a3 --- /dev/null +++ b/private/mgmtapi/tools/BUILD.bazel @@ -0,0 +1,10 @@ +load("@npm//:defs.bzl", "npm_link_all_packages") + +exports_files( + [ + "package.json", + "pnpm-lock.yml", + ], +) + +npm_link_all_packages(name = "node_modules") diff --git a/private/mgmtapi/tools/package.json b/private/mgmtapi/tools/package.json new file mode 100644 index 000000000..e1829ea07 --- /dev/null +++ b/private/mgmtapi/tools/package.json @@ -0,0 +1,30 @@ +{ + "dependencies": { + "@redocly/cli": "1.0.2", + "@stoplight/spectral-cli": "^6.11.0", + "lodash.get": "^4.4.2", + "lodash.set": "^4.3.2" + }, + "pnpm": { + "packageExtensions": { + "styled-components@5.3.11": { + "dependencies": { + "react-is": "18.2.0" + } + }, + "@redocly/cli": { + "dependencies": { + "lodash.isequal": "4.5.0", + "node-fetch": "2.6.7" + } + }, + "redoc@~2.0.0": { + "dependencies": { + "call-me-maybe": "1.0.2", + "yaml": "2.1.3", + "fast-safe-stringify": "2.1.1" + } + } + } + } +} diff --git a/private/mgmtapi/tools/pnpm-lock.yaml b/private/mgmtapi/tools/pnpm-lock.yaml new file mode 100644 index 000000000..6f9a43047 --- /dev/null +++ b/private/mgmtapi/tools/pnpm-lock.yaml @@ -0,0 +1,3231 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +packageExtensionsChecksum: 12431cddfbc961e47dea32fc33af3a5c + +dependencies: + '@redocly/cli': + specifier: 1.0.2 + version: 1.0.2(@babel/core@7.23.2)(core-js@3.33.1)(react-is@16.13.1)(webpack@5.89.0) + '@stoplight/spectral-cli': + specifier: ^6.11.0 + version: 6.11.0 + lodash.get: + specifier: ^4.4.2 + version: 4.4.2 + lodash.set: + specifier: ^4.3.2 + version: 4.3.2 + +packages: + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + dev: false + + /@asyncapi/specs@4.3.1: + resolution: {integrity: sha512-EfexhJu/lwF8OdQDm28NKLJHFkx0Gb6O+rcezhZYLPIoNYKXJMh2J1vFGpwmfAcTTh+ffK44Oc2Hs1Q4sLBp+A==} + dependencies: + '@types/json-schema': 7.0.14 + dev: false + + /@babel/code-frame@7.22.13: + resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.22.20 + chalk: 2.4.2 + dev: false + + /@babel/compat-data@7.23.2: + resolution: {integrity: sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/core@7.23.2: + resolution: {integrity: sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.0 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.2) + '@babel/helpers': 7.23.2 + '@babel/parser': 7.23.0 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.2(supports-color@5.5.0) + '@babel/types': 7.23.0 + convert-source-map: 2.0.0 + debug: 4.3.4(supports-color@5.5.0) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/generator@7.23.0: + resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + jsesc: 2.5.2 + dev: false + + /@babel/helper-annotate-as-pure@7.22.5: + resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-compilation-targets@7.22.15: + resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.23.2 + '@babel/helper-validator-option': 7.22.15 + browserslist: 4.22.1 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: false + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-module-transforms@7.23.0(@babel/core@7.23.2): + resolution: {integrity: sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: false + + /@babel/helper-plugin-utils@7.22.5: + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-string-parser@7.22.5: + resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-validator-option@7.22.15: + resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helpers@7.23.2: + resolution: {integrity: sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.2(supports-color@5.5.0) + '@babel/types': 7.23.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/highlight@7.22.20: + resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: false + + /@babel/parser@7.23.0: + resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.23.2): + resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/runtime@7.23.2: + resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.0 + dev: false + + /@babel/template@7.22.15: + resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + dev: false + + /@babel/traverse@7.23.2(supports-color@5.5.0): + resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.0 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + debug: 4.3.4(supports-color@5.5.0) + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/types@7.23.0: + resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: false + + /@emotion/is-prop-valid@1.2.1: + resolution: {integrity: sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==} + dependencies: + '@emotion/memoize': 0.8.1 + dev: false + + /@emotion/memoize@0.8.1: + resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} + dev: false + + /@emotion/stylis@0.8.5: + resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} + dev: false + + /@emotion/unitless@0.7.5: + resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} + dev: false + + /@exodus/schemasafe@1.3.0: + resolution: {integrity: sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==} + dev: false + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.20 + dev: false + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: false + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: false + + /@jridgewell/source-map@0.3.5: + resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + dev: false + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: false + + /@jridgewell/trace-mapping@0.3.20: + resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + + /@jsep-plugin/regex@1.0.3(jsep@1.3.8): + resolution: {integrity: sha512-XfZgry4DwEZvSFtS/6Y+R48D7qJYJK6R9/yJFyUFHCIUMEEHuJ4X95TDgJp5QkmzfLYvapMPzskV5HpIDrREug==} + engines: {node: '>= 10.16.0'} + peerDependencies: + jsep: ^0.4.0||^1.0.0 + dependencies: + jsep: 1.3.8 + dev: false + + /@jsep-plugin/ternary@1.1.3(jsep@1.3.8): + resolution: {integrity: sha512-qtLGzCNzPVJ3kdH6/zoLWDPjauHIKiLSBAR71Wa0+PWvGA8wODUQvRgxtpUA5YqAYL3CQ8S4qXhd/9WuWTZirg==} + engines: {node: '>= 10.16.0'} + peerDependencies: + jsep: ^0.4.0||^1.0.0 + dependencies: + jsep: 1.3.8 + dev: false + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: false + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: false + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: false + + /@redocly/ajv@8.11.0: + resolution: {integrity: sha512-9GWx27t7xWhDIR02PA18nzBdLcKQRgc46xNQvjFkrYk4UOmvKhJ/dawwiX0cCOeetN5LcaaiqQbVOWYK62SGHw==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: false + + /@redocly/cli@1.0.2(@babel/core@7.23.2)(core-js@3.33.1)(react-is@16.13.1)(webpack@5.89.0): + resolution: {integrity: sha512-IWuo5V2ZKSdvQMgNx05PHBlv1YvqJH3/nX52qslooEtqsvOaCUnZIm/aCd1zw2EW5Ub2+VLb51LqMt6mDF/9vQ==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + '@redocly/openapi-core': 1.0.2 + assert-node-version: 1.0.3 + chokidar: 3.5.3 + colorette: 1.4.0 + glob: 7.2.3 + glob-promise: 3.4.0(glob@7.2.3) + handlebars: 4.7.7 + lodash.isequal: 4.5.0 + mobx: 6.10.2 + node-fetch: 2.6.7 + portfinder: 1.0.32 + react: 17.0.2 + react-dom: 17.0.2(react@17.0.2) + redoc: 2.0.0(core-js@3.33.1)(mobx@6.10.2)(react-dom@17.0.2)(react@17.0.2)(styled-components@5.3.11)(webpack@5.89.0) + semver: 7.5.4 + simple-websocket: 9.1.0 + styled-components: 5.3.11(@babel/core@7.23.2)(react-dom@17.0.2)(react-is@16.13.1)(react@17.0.2) + yargs: 17.0.1 + transitivePeerDependencies: + - '@babel/core' + - bufferutil + - core-js + - encoding + - react-is + - react-native + - supports-color + - utf-8-validate + - webpack + dev: false + + /@redocly/openapi-core@1.0.2: + resolution: {integrity: sha512-53dzhmG2bsi/8rcAAgBKk9ZLMR035VHgN7oSM3+BM4UAIoNBg6lMC/ChHSf9zO+GrX5qtuWVPqHhjjMti3SAlQ==} + engines: {node: '>=12.0.0'} + dependencies: + '@redocly/ajv': 8.11.0 + '@types/node': 14.18.21 + colorette: 1.4.0 + js-levenshtein: 1.1.6 + js-yaml: 4.1.0 + lodash.isequal: 4.5.0 + minimatch: 5.1.0 + node-fetch: 2.6.7 + pluralize: 8.0.0 + yaml-ast-parser: 0.0.43 + transitivePeerDependencies: + - encoding + dev: false + + /@redocly/openapi-core@1.4.0: + resolution: {integrity: sha512-M4f0H3XExPvJ0dwbEou7YKLzkpz2ZMS9JoNvrbEECO7WCwjGZ4AjbiUjp2p0ZzFMNIiNgTVUJJmkxGxsXW471Q==} + engines: {node: '>=14.19.0', npm: '>=7.0.0'} + dependencies: + '@redocly/ajv': 8.11.0 + '@types/node': 14.18.21 + colorette: 1.4.0 + js-levenshtein: 1.1.6 + js-yaml: 4.1.0 + lodash.isequal: 4.5.0 + minimatch: 5.1.0 + node-fetch: 2.6.7 + pluralize: 8.0.0 + yaml-ast-parser: 0.0.43 + transitivePeerDependencies: + - encoding + dev: false + + /@rollup/plugin-commonjs@22.0.2(rollup@2.79.1): + resolution: {integrity: sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==} + engines: {node: '>= 12.0.0'} + peerDependencies: + rollup: ^2.68.0 + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.1) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 7.2.3 + is-reference: 1.2.1 + magic-string: 0.25.9 + resolve: 1.22.8 + rollup: 2.79.1 + dev: false + + /@rollup/pluginutils@3.1.0(rollup@2.79.1): + resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.79.1 + dev: false + + /@stoplight/better-ajv-errors@1.0.3(ajv@8.12.0): + resolution: {integrity: sha512-0p9uXkuB22qGdNfy3VeEhxkU5uwvp/KrBTAbrLBURv6ilxIVwanKwjMc41lQfIVgPGcOkmLbTolfFrSsueu7zA==} + engines: {node: ^12.20 || >= 14.13} + peerDependencies: + ajv: '>=8' + dependencies: + ajv: 8.12.0 + jsonpointer: 5.0.1 + leven: 3.1.0 + dev: false + + /@stoplight/json-ref-readers@1.2.2: + resolution: {integrity: sha512-nty0tHUq2f1IKuFYsLM4CXLZGHdMn+X/IwEUIpeSOXt0QjMUbL0Em57iJUDzz+2MkWG83smIigNZ3fauGjqgdQ==} + engines: {node: '>=8.3.0'} + dependencies: + node-fetch: 2.6.7 + tslib: 1.14.1 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/json-ref-resolver@3.1.6: + resolution: {integrity: sha512-YNcWv3R3n3U6iQYBsFOiWSuRGE5su1tJSiX6pAPRVk7dP0L7lqCteXGzuVRQ0gMZqUl8v1P0+fAKxF6PLo9B5A==} + engines: {node: '>=8.3.0'} + dependencies: + '@stoplight/json': 3.21.0 + '@stoplight/path': 1.3.2 + '@stoplight/types': 13.20.0 + '@types/urijs': 1.19.22 + dependency-graph: 0.11.0 + fast-memoize: 2.5.2 + immer: 9.0.21 + lodash: 4.17.21 + tslib: 2.6.2 + urijs: 1.19.11 + dev: false + + /@stoplight/json@3.21.0: + resolution: {integrity: sha512-5O0apqJ/t4sIevXCO3SBN9AHCEKKR/Zb4gaj7wYe5863jme9g02Q0n/GhM7ZCALkL+vGPTe4ZzTETP8TFtsw3g==} + engines: {node: '>=8.3.0'} + dependencies: + '@stoplight/ordered-object-literal': 1.0.4 + '@stoplight/path': 1.3.2 + '@stoplight/types': 13.20.0 + jsonc-parser: 2.2.1 + lodash: 4.17.21 + safe-stable-stringify: 1.1.1 + dev: false + + /@stoplight/ordered-object-literal@1.0.4: + resolution: {integrity: sha512-OF8uib1jjDs5/cCU+iOVy+GJjU3X7vk/qJIkIJFqwmlJKrrtijFmqwbu8XToXrwTYLQTP+Hebws5gtZEmk9jag==} + engines: {node: '>=8'} + dev: false + + /@stoplight/path@1.3.2: + resolution: {integrity: sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ==} + engines: {node: '>=8'} + dev: false + + /@stoplight/spectral-cli@6.11.0: + resolution: {integrity: sha512-IURDN47BPIf3q4ZyUPujGpBzuHWFE5yT34w9rTJ1GKA4SgdscEdQO9KoTjOPT4G4cvDlEV3bNxwQ3uRm7+wRlA==} + engines: {node: ^12.20 || >= 14.13} + hasBin: true + dependencies: + '@stoplight/json': 3.21.0 + '@stoplight/path': 1.3.2 + '@stoplight/spectral-core': 1.18.3 + '@stoplight/spectral-formatters': 1.3.0 + '@stoplight/spectral-parsers': 1.0.3 + '@stoplight/spectral-ref-resolver': 1.0.4 + '@stoplight/spectral-ruleset-bundler': 1.5.2 + '@stoplight/spectral-ruleset-migrator': 1.9.5 + '@stoplight/spectral-rulesets': 1.18.0 + '@stoplight/spectral-runtime': 1.1.2 + '@stoplight/types': 13.20.0 + chalk: 4.1.2 + fast-glob: 3.2.12 + hpagent: 1.2.0 + lodash: 4.17.21 + pony-cause: 1.1.1 + stacktracey: 2.1.8 + tslib: 2.6.2 + yargs: 17.3.1 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/spectral-core@1.18.3: + resolution: {integrity: sha512-YY8x7X2SWJIhGTLPol+eFiQpWPz0D0mJdkK2i4A0QJG68KkNhypP6+JBC7/Kz3XWjqr0L/RqAd+N5cQLPOKZGQ==} + engines: {node: ^12.20 || >= 14.13} + dependencies: + '@stoplight/better-ajv-errors': 1.0.3(ajv@8.12.0) + '@stoplight/json': 3.21.0 + '@stoplight/path': 1.3.2 + '@stoplight/spectral-parsers': 1.0.3 + '@stoplight/spectral-ref-resolver': 1.0.4 + '@stoplight/spectral-runtime': 1.1.2 + '@stoplight/types': 13.6.0 + '@types/es-aggregate-error': 1.0.4 + '@types/json-schema': 7.0.14 + ajv: 8.12.0 + ajv-errors: 3.0.0(ajv@8.12.0) + ajv-formats: 2.1.1(ajv@8.12.0) + es-aggregate-error: 1.0.11 + jsonpath-plus: 7.1.0 + lodash: 4.17.21 + lodash.topath: 4.5.2 + minimatch: 3.1.2 + nimma: 0.2.2 + pony-cause: 1.1.1 + simple-eval: 1.0.0 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/spectral-formats@1.5.0: + resolution: {integrity: sha512-VskkdU3qBSvI1dfJ79ysjvTssfNlbA6wrf/XkXK6iTyjfIVqOAWVtjypTb2U95tN/X8IjIBBhNWtZ4tNVZilrA==} + engines: {node: '>=12'} + dependencies: + '@stoplight/json': 3.21.0 + '@stoplight/spectral-core': 1.18.3 + '@types/json-schema': 7.0.14 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/spectral-formatters@1.3.0: + resolution: {integrity: sha512-ryuMwlzbPUuyn7ybSEbFYsljYmvTaTyD51wyCQs4ROzgfm3Yo5QDD0IsiJUzUpKK/Ml61ZX8ebgiPiRFEJtBpg==} + engines: {node: ^12.20 || >=14.13} + dependencies: + '@stoplight/path': 1.3.2 + '@stoplight/spectral-core': 1.18.3 + '@stoplight/spectral-runtime': 1.1.2 + '@stoplight/types': 13.20.0 + chalk: 4.1.2 + cliui: 7.0.4 + lodash: 4.17.21 + node-sarif-builder: 2.0.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/spectral-functions@1.7.2: + resolution: {integrity: sha512-f+61/FtIkQeIo+a269CeaeqjpyRsgDyIk6DGr7iS4hyuk1PPk7Uf6MNRDs9FEIBh7CpdEJ+HSHbMLwgpymWTIw==} + engines: {node: '>=12'} + dependencies: + '@stoplight/better-ajv-errors': 1.0.3(ajv@8.12.0) + '@stoplight/json': 3.21.0 + '@stoplight/spectral-core': 1.18.3 + '@stoplight/spectral-formats': 1.5.0 + '@stoplight/spectral-runtime': 1.1.2 + ajv: 8.12.0 + ajv-draft-04: 1.0.0(ajv@8.12.0) + ajv-errors: 3.0.0(ajv@8.12.0) + ajv-formats: 2.1.1(ajv@8.12.0) + lodash: 4.17.21 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/spectral-parsers@1.0.3: + resolution: {integrity: sha512-J0KW5Rh5cHWnJQ3yN+cr/ijNFVirPSR0pkQbdrNX30VboEl083UEDrQ3yov9kjLVIWEk9t9kKE7Eo3QT/k4JLA==} + engines: {node: ^12.20 || >=14.13} + dependencies: + '@stoplight/json': 3.21.0 + '@stoplight/types': 13.20.0 + '@stoplight/yaml': 4.2.3 + tslib: 2.6.2 + dev: false + + /@stoplight/spectral-ref-resolver@1.0.4: + resolution: {integrity: sha512-5baQIYL0NJTSVy8v6RxOR4U51xOUYM8wJri1YvlAT6bPN8m0EIxMwfVYi0xUZEMVeHcWx869nIkoqyWmOutF2A==} + engines: {node: '>=12'} + dependencies: + '@stoplight/json-ref-readers': 1.2.2 + '@stoplight/json-ref-resolver': 3.1.6 + '@stoplight/spectral-runtime': 1.1.2 + dependency-graph: 0.11.0 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/spectral-ruleset-bundler@1.5.2: + resolution: {integrity: sha512-4QUVUFAU+S7IQ9XeCu+0TQMYxKFpKnkOAfa9unRQ1iPL2cviaipEN6witpbAptdHJD3UUjx4OnwlX8WwmXSq9w==} + engines: {node: ^12.20 || >= 14.13} + dependencies: + '@rollup/plugin-commonjs': 22.0.2(rollup@2.79.1) + '@stoplight/path': 1.3.2 + '@stoplight/spectral-core': 1.18.3 + '@stoplight/spectral-formats': 1.5.0 + '@stoplight/spectral-functions': 1.7.2 + '@stoplight/spectral-parsers': 1.0.3 + '@stoplight/spectral-ref-resolver': 1.0.4 + '@stoplight/spectral-ruleset-migrator': 1.9.5 + '@stoplight/spectral-rulesets': 1.18.0 + '@stoplight/spectral-runtime': 1.1.2 + '@stoplight/types': 13.20.0 + '@types/node': 14.18.21 + pony-cause: 1.1.1 + rollup: 2.79.1 + tslib: 2.6.2 + validate-npm-package-name: 3.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/spectral-ruleset-migrator@1.9.5: + resolution: {integrity: sha512-76n/HETr3UinVl/xLNldrH9p0JNoD8Gz4K75J6E4OHp4xD0P+BA2e8+W30HjIvqm1LJdLU2BNma0ioy+q3B9RA==} + engines: {node: '>=12'} + dependencies: + '@stoplight/json': 3.21.0 + '@stoplight/ordered-object-literal': 1.0.4 + '@stoplight/path': 1.3.2 + '@stoplight/spectral-functions': 1.7.2 + '@stoplight/spectral-runtime': 1.1.2 + '@stoplight/types': 13.20.0 + '@stoplight/yaml': 4.2.3 + '@types/node': 14.18.21 + ajv: 8.12.0 + ast-types: 0.14.2 + astring: 1.8.6 + reserved: 0.1.2 + tslib: 2.6.2 + validate-npm-package-name: 3.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/spectral-rulesets@1.18.0: + resolution: {integrity: sha512-7LiCteW5pofMuBtf1BO+Ig5pT1XV9oqGrUjqWwSqD6jcy8ejE45pOQpef4h4um9tj3Y+tewfdbthLjhu8sdoeA==} + engines: {node: '>=12'} + dependencies: + '@asyncapi/specs': 4.3.1 + '@stoplight/better-ajv-errors': 1.0.3(ajv@8.12.0) + '@stoplight/json': 3.21.0 + '@stoplight/spectral-core': 1.18.3 + '@stoplight/spectral-formats': 1.5.0 + '@stoplight/spectral-functions': 1.7.2 + '@stoplight/spectral-runtime': 1.1.2 + '@stoplight/types': 13.20.0 + '@types/json-schema': 7.0.14 + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + json-schema-traverse: 1.0.0 + lodash: 4.17.21 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/spectral-runtime@1.1.2: + resolution: {integrity: sha512-fr5zRceXI+hrl82yAVoME+4GvJie8v3wmOe9tU+ZLRRNonizthy8qDi0Z/z4olE+vGreSDcuDOZ7JjRxFW5kTw==} + engines: {node: '>=12'} + dependencies: + '@stoplight/json': 3.21.0 + '@stoplight/path': 1.3.2 + '@stoplight/types': 12.5.0 + abort-controller: 3.0.0 + lodash: 4.17.21 + node-fetch: 2.6.7 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + dev: false + + /@stoplight/types@12.5.0: + resolution: {integrity: sha512-dwqYcDrGmEyUv5TWrDam5TGOxU72ufyQ7hnOIIDdmW5ezOwZaBFoR5XQ9AsH49w7wgvOqB2Bmo799pJPWnpCbg==} + engines: {node: '>=8'} + dependencies: + '@types/json-schema': 7.0.14 + utility-types: 3.10.0 + dev: false + + /@stoplight/types@13.20.0: + resolution: {integrity: sha512-2FNTv05If7ib79VPDA/r9eUet76jewXFH2y2K5vuge6SXbRHtWBhcaRmu+6QpF4/WRNoJj5XYRSwLGXDxysBGA==} + engines: {node: ^12.20 || >=14.13} + dependencies: + '@types/json-schema': 7.0.14 + utility-types: 3.10.0 + dev: false + + /@stoplight/types@13.6.0: + resolution: {integrity: sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==} + engines: {node: ^12.20 || >=14.13} + dependencies: + '@types/json-schema': 7.0.14 + utility-types: 3.10.0 + dev: false + + /@stoplight/yaml-ast-parser@0.0.48: + resolution: {integrity: sha512-sV+51I7WYnLJnKPn2EMWgS4EUfoP4iWEbrWwbXsj0MZCB/xOK8j6+C9fntIdOM50kpx45ZLC3s6kwKivWuqvyg==} + dev: false + + /@stoplight/yaml@4.2.3: + resolution: {integrity: sha512-Mx01wjRAR9C7yLMUyYFTfbUf5DimEpHMkRDQ1PKLe9dfNILbgdxyrncsOXM3vCpsQ1Hfj4bPiGl+u4u6e9Akqw==} + engines: {node: '>=10.8'} + dependencies: + '@stoplight/ordered-object-literal': 1.0.4 + '@stoplight/types': 13.20.0 + '@stoplight/yaml-ast-parser': 0.0.48 + tslib: 2.6.2 + dev: false + + /@types/es-aggregate-error@1.0.4: + resolution: {integrity: sha512-95tL6tLR8P3Utx4SxXUEc0e+k2B9VhtBozhgxKGpv30ylIuxGxf080d7mYZ08sH5UjpDv/Nd6F80tH1p+KuPIg==} + dependencies: + '@types/node': 14.18.21 + dev: false + + /@types/eslint-scope@3.7.6: + resolution: {integrity: sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==} + dependencies: + '@types/eslint': 8.44.6 + '@types/estree': 1.0.3 + dev: false + + /@types/eslint@8.44.6: + resolution: {integrity: sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==} + dependencies: + '@types/estree': 1.0.3 + '@types/json-schema': 7.0.14 + dev: false + + /@types/estree@0.0.39: + resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + dev: false + + /@types/estree@1.0.3: + resolution: {integrity: sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==} + dev: false + + /@types/glob@8.1.0: + resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 14.18.21 + dev: false + + /@types/json-schema@7.0.14: + resolution: {integrity: sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==} + dev: false + + /@types/minimatch@5.1.2: + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + dev: false + + /@types/node@14.18.21: + resolution: {integrity: sha512-x5W9s+8P4XteaxT/jKF0PSb7XEvo5VmqEWgsMlyeY4ZlLK8I6aH6g5TPPyDlLAep+GYf4kefb7HFyc7PAO3m+Q==} + dev: false + + /@types/sarif@2.1.6: + resolution: {integrity: sha512-x+68l19JJnfXX9oq85k6KZwsPuOa2BKESkYqbRbA09zLSZXIDNyDo1illgDB/P0ZdpIa4EII3pHJ6DQq3xo3Qw==} + dev: false + + /@types/urijs@1.19.22: + resolution: {integrity: sha512-qnYBwfN7O/+i6E1Kr8JaCKsrCLpRCiQ1XxkSxNIYuJ/5Aagt0+HlMX78DJMUrNzDULMz0eu2gcprlxJaDtACOw==} + dev: false + + /@webassemblyjs/ast@1.11.6: + resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==} + dependencies: + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + dev: false + + /@webassemblyjs/floating-point-hex-parser@1.11.6: + resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} + dev: false + + /@webassemblyjs/helper-api-error@1.11.6: + resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} + dev: false + + /@webassemblyjs/helper-buffer@1.11.6: + resolution: {integrity: sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==} + dev: false + + /@webassemblyjs/helper-numbers@1.11.6: + resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@xtuc/long': 4.2.2 + dev: false + + /@webassemblyjs/helper-wasm-bytecode@1.11.6: + resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} + dev: false + + /@webassemblyjs/helper-wasm-section@1.11.6: + resolution: {integrity: sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + dev: false + + /@webassemblyjs/ieee754@1.11.6: + resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: false + + /@webassemblyjs/leb128@1.11.6: + resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} + dependencies: + '@xtuc/long': 4.2.2 + dev: false + + /@webassemblyjs/utf8@1.11.6: + resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} + dev: false + + /@webassemblyjs/wasm-edit@1.11.6: + resolution: {integrity: sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-opt': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + '@webassemblyjs/wast-printer': 1.11.6 + dev: false + + /@webassemblyjs/wasm-gen@1.11.6: + resolution: {integrity: sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: false + + /@webassemblyjs/wasm-opt@1.11.6: + resolution: {integrity: sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + dev: false + + /@webassemblyjs/wasm-parser@1.11.6: + resolution: {integrity: sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: false + + /@webassemblyjs/wast-printer@1.11.6: + resolution: {integrity: sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@xtuc/long': 4.2.2 + dev: false + + /@xtuc/ieee754@1.2.0: + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + dev: false + + /@xtuc/long@4.2.2: + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + dev: false + + /abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + dependencies: + event-target-shim: 5.0.1 + dev: false + + /acorn-import-assertions@1.9.0(acorn@8.11.2): + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + peerDependencies: + acorn: ^8 + dependencies: + acorn: 8.11.2 + dev: false + + /acorn@8.11.2: + resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + + /ajv-draft-04@1.0.0(ajv@8.12.0): + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.12.0 + dev: false + + /ajv-errors@3.0.0(ajv@8.12.0): + resolution: {integrity: sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==} + peerDependencies: + ajv: ^8.0.1 + dependencies: + ajv: 8.12.0 + dev: false + + /ajv-formats@2.1.1(ajv@8.12.0): + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.12.0 + dev: false + + /ajv-keywords@3.5.2(ajv@6.12.6): + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + dev: false + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: false + + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: false + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: false + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: false + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: false + + /anymatch@3.1.2: + resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: false + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: false + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.5 + is-array-buffer: 3.0.2 + dev: false + + /arraybuffer.prototype.slice@1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: false + + /as-table@1.0.55: + resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} + dependencies: + printable-characters: 1.0.42 + dev: false + + /assert-node-version@1.0.3: + resolution: {integrity: sha512-XcKBGJ1t0RrCcus9dQX57FER4PTEz/+Tee2jj+EdFIGyw5j8hwDNXZzgRYLQ916twVjSuA47adrZsSxLbpEX9A==} + engines: {node: '>=0.10.0'} + dependencies: + expected-node-version: 1.0.2 + semver: 5.7.2 + dev: false + + /ast-types@0.14.2: + resolution: {integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==} + engines: {node: '>=4'} + dependencies: + tslib: 2.6.2 + dev: false + + /astring@1.8.6: + resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} + hasBin: true + dev: false + + /async@2.6.4: + resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} + dependencies: + lodash: 4.17.21 + dev: false + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: false + + /babel-plugin-styled-components@2.1.4(@babel/core@7.23.2)(styled-components@5.3.11): + resolution: {integrity: sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==} + peerDependencies: + styled-components: '>= 2' + dependencies: + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-module-imports': 7.22.15 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.2) + lodash: 4.17.21 + picomatch: 2.3.1 + styled-components: 5.3.11(@babel/core@7.23.2)(react-dom@17.0.2)(react-is@16.13.1)(react@17.0.2) + transitivePeerDependencies: + - '@babel/core' + dev: false + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: false + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: false + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: false + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: false + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: false + + /browserslist@4.22.1: + resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001558 + electron-to-chromium: 1.4.569 + node-releases: 2.0.13 + update-browserslist-db: 1.0.13(browserslist@4.22.1) + dev: false + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: false + + /builtins@1.0.3: + resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==} + dev: false + + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + dependencies: + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.1.1 + dev: false + + /call-me-maybe@1.0.2: + resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} + dev: false + + /camelize@1.0.1: + resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} + dev: false + + /caniuse-lite@1.0.30001558: + resolution: {integrity: sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==} + dev: false + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: false + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.2 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: false + + /chrome-trace-event@1.0.3: + resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + engines: {node: '>=6.0'} + dev: false + + /classnames@2.3.2: + resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} + dev: false + + /cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + + /clsx@1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + dev: false + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: false + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: false + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: false + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: false + + /colorette@1.4.0: + resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} + dev: false + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: false + + /commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: false + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: false + + /core-js@3.33.1: + resolution: {integrity: sha512-qVSq3s+d4+GsqN0teRCJtM6tdEEXyWxjzbhVrCHmBS5ZTM0FS2MOS0D13dUXAWDUN6a+lHI/N1hF9Ytz6iLl9Q==} + requiresBuild: true + dev: false + + /css-color-keywords@1.0.0: + resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} + engines: {node: '>=4'} + dev: false + + /css-to-react-native@3.2.0: + resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} + dependencies: + camelize: 1.0.1 + css-color-keywords: 1.0.0 + postcss-value-parser: 4.2.0 + dev: false + + /data-uri-to-buffer@2.0.2: + resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} + dev: false + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + + /debug@4.3.4(supports-color@5.5.0): + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + supports-color: 5.5.0 + dev: false + + /decko@1.2.0: + resolution: {integrity: sha512-m8FnyHXV1QX+S1cl+KPFDIl6NMkxtKsy6+U/aYyjrOqWMuwAwYWu7ePqrsUHtDR5Y8Yk2pi/KIDSgF+vT4cPOQ==} + dev: false + + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: false + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + has-property-descriptors: 1.0.1 + object-keys: 1.1.1 + dev: false + + /dependency-graph@0.11.0: + resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} + engines: {node: '>= 0.6.0'} + dev: false + + /dompurify@2.4.7: + resolution: {integrity: sha512-kxxKlPEDa6Nc5WJi+qRgPbOAbgTpSULL+vI3NUXsZMlkJxTqYI9wg5ZTay2sFrdZRWHPWNi+EdAhcJf81WtoMQ==} + dev: false + + /electron-to-chromium@1.4.569: + resolution: {integrity: sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==} + dev: false + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: false + + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: false + + /es-abstract@1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.2 + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + es-set-tostringtag: 2.0.2 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.2 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + internal-slot: 1.0.6 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.1 + safe-array-concat: 1.0.1 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.8 + string.prototype.trimend: 1.0.7 + string.prototype.trimstart: 1.0.7 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.13 + dev: false + + /es-aggregate-error@1.0.11: + resolution: {integrity: sha512-DCiZiNlMlbvofET/cE55My387NiLvuGToBEZDdK9U2G3svDCjL8WOgO5Il6lO83nQ8qmag/R9nArdpaFQ/m3lA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + define-properties: 1.2.1 + es-abstract: 1.22.3 + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + globalthis: 1.0.3 + has-property-descriptors: 1.0.1 + set-function-name: 2.0.1 + dev: false + + /es-module-lexer@1.3.1: + resolution: {integrity: sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==} + dev: false + + /es-set-tostringtag@2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + has-tostringtag: 1.0.0 + hasown: 2.0.0 + dev: false + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: false + + /es6-promise@3.3.1: + resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + dev: false + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: false + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: false + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: false + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: false + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: false + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: false + + /estree-walker@1.0.1: + resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} + dev: false + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: false + + /event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + dev: false + + /eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + dev: false + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: false + + /expected-node-version@1.0.2: + resolution: {integrity: sha512-OSaCdgF02srujDqJz1JWGpqk8Rq3uNYHLmtpBHJrZN3BvuMvzijJMqRVxZN1qLJtKVwjXhmOp+lfsRUqx8n54w==} + engines: {node: '>=0.10.0'} + dev: false + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: false + + /fast-glob@3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: false + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: false + + /fast-memoize@2.5.2: + resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==} + dev: false + + /fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + dev: false + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: false + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: false + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: false + + /foreach@2.0.6: + resolution: {integrity: sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==} + dev: false + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: false + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: false + + /fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: false + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + functions-have-names: 1.2.3 + dev: false + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: false + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: false + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: false + + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + dependencies: + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + dev: false + + /get-source@2.0.12: + resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} + dependencies: + data-uri-to-buffer: 2.0.2 + source-map: 0.6.1 + dev: false + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + dev: false + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: false + + /glob-promise@3.4.0(glob@7.2.3): + resolution: {integrity: sha512-q08RJ6O+eJn+dVanerAndJwIcumgbDdYiUT7zFQl3Wm1xD6fBKtah7H8ZJChj4wP+8C+QfeVy8xautR7rdmKEw==} + engines: {node: '>=4'} + peerDependencies: + glob: '*' + dependencies: + '@types/glob': 8.1.0 + glob: 7.2.3 + dev: false + + /glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: false + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: false + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: false + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.2 + dev: false + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: false + + /handlebars@4.7.7: + resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.6 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.16.0 + dev: false + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: false + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: false + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: false + + /has-property-descriptors@1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + dependencies: + get-intrinsic: 1.2.2 + dev: false + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: false + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: false + + /hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + dependencies: + react-is: 16.13.1 + dev: false + + /hpagent@1.2.0: + resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} + engines: {node: '>=14'} + dev: false + + /http2-client@1.3.5: + resolution: {integrity: sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==} + dev: false + + /immer@9.0.21: + resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} + dev: false + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /internal-slot@1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + hasown: 2.0.0 + side-channel: 1.0.4 + dev: false + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: false + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: false + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: false + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: false + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: false + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 + dev: false + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: false + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: false + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: false + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: false + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: false + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: false + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: false + + /is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + dependencies: + '@types/estree': 1.0.3 + dev: false + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: false + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.5 + dev: false + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: false + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: false + + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.13 + dev: false + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.5 + dev: false + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: false + + /jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 14.18.21 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: false + + /js-levenshtein@1.1.6: + resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} + engines: {node: '>=0.10.0'} + dev: false + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: false + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: false + + /jsep@1.3.8: + resolution: {integrity: sha512-qofGylTGgYj9gZFsHuyWAN4jr35eJ66qJCK4eKDnldohuUoQFbU3iZn2zjvEbd9wOAhP9Wx5DsAAduTyE1PSWQ==} + engines: {node: '>= 10.16.0'} + dev: false + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: false + + /json-pointer@0.6.2: + resolution: {integrity: sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==} + dependencies: + foreach: 2.0.6 + dev: false + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: false + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: false + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: false + + /jsonc-parser@2.2.1: + resolution: {integrity: sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==} + dev: false + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.11 + dev: false + + /jsonpath-plus@6.0.1: + resolution: {integrity: sha512-EvGovdvau6FyLexFH2OeXfIITlgIbgZoAZe3usiySeaIDm5QS+A10DKNpaPBBqqRSZr2HN6HVNXxtwUAr2apEw==} + engines: {node: '>=10.0.0'} + requiresBuild: true + dev: false + optional: true + + /jsonpath-plus@7.1.0: + resolution: {integrity: sha512-gTaNRsPWO/K2KY6MrqaUFClF9kmuM6MFH5Dhg1VYDODgFbByw1yb7xu3hrViE/sz+dGOeMWgCzwUwQtAnCTE9g==} + engines: {node: '>=12.0.0'} + dev: false + + /jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + dev: false + + /leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: false + + /loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + dev: false + + /lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + dev: false + + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: false + + /lodash.set@4.3.2: + resolution: {integrity: sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==} + dev: false + + /lodash.topath@4.5.2: + resolution: {integrity: sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==} + dev: false + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: false + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: false + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: false + + /lunr@2.3.9: + resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + dev: false + + /magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + dependencies: + sourcemap-codec: 1.4.8 + dev: false + + /mark.js@8.11.1: + resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} + dev: false + + /marked@4.3.0: + resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} + engines: {node: '>= 12'} + hasBin: true + dev: false + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: false + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: false + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: false + + /minimatch@5.1.0: + resolution: {integrity: sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimist@1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + dev: false + + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.6 + dev: false + + /mobx-react-lite@3.4.3(mobx@6.10.2)(react-dom@17.0.2)(react@17.0.2): + resolution: {integrity: sha512-NkJREyFTSUXR772Qaai51BnE1voWx56LOL80xG7qkZr6vo8vEaLF3sz1JNUVh+rxmUzxYaqOhfuxTfqUh0FXUg==} + peerDependencies: + mobx: ^6.1.0 + react: ^16.8.0 || ^17 || ^18 + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + dependencies: + mobx: 6.10.2 + react: 17.0.2 + react-dom: 17.0.2(react@17.0.2) + dev: false + + /mobx-react@7.6.0(mobx@6.10.2)(react-dom@17.0.2)(react@17.0.2): + resolution: {integrity: sha512-+HQUNuh7AoQ9ZnU6c4rvbiVVl+wEkb9WqYsVDzGLng+Dqj1XntHu79PvEWKtSMoMj67vFp/ZPXcElosuJO8ckA==} + peerDependencies: + mobx: ^6.1.0 + react: ^16.8.0 || ^17 || ^18 + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + dependencies: + mobx: 6.10.2 + mobx-react-lite: 3.4.3(mobx@6.10.2)(react-dom@17.0.2)(react@17.0.2) + react: 17.0.2 + react-dom: 17.0.2(react@17.0.2) + dev: false + + /mobx@6.10.2: + resolution: {integrity: sha512-B1UGC3ieK3boCjnMEcZSwxqRDMdzX65H/8zOHbuTY8ZhvrIjTUoLRR2TP2bPqIgYRfb3+dUigu8yMZufNjn0LQ==} + dev: false + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: false + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: false + + /nimma@0.2.2: + resolution: {integrity: sha512-V52MLl7BU+tH2Np9tDrIXK8bql3MVUadnMIl/0/oZSGC9keuro0O9UUv9QKp0aMvtN8HRew4G7byY7H4eWsxaQ==} + engines: {node: ^12.20 || >=14.13} + dependencies: + '@jsep-plugin/regex': 1.0.3(jsep@1.3.8) + '@jsep-plugin/ternary': 1.1.3(jsep@1.3.8) + astring: 1.8.6 + jsep: 1.3.8 + optionalDependencies: + jsonpath-plus: 6.0.1 + lodash.topath: 4.5.2 + dev: false + + /node-fetch-h2@2.3.0: + resolution: {integrity: sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==} + engines: {node: 4.x || >=6.0.0} + dependencies: + http2-client: 1.3.5 + dev: false + + /node-fetch@2.6.7: + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + + /node-readfiles@0.2.0: + resolution: {integrity: sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==} + dependencies: + es6-promise: 3.3.1 + dev: false + + /node-releases@2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} + dev: false + + /node-sarif-builder@2.0.3: + resolution: {integrity: sha512-Pzr3rol8fvhG/oJjIq2NTVB0vmdNNlz22FENhhPojYRZ4/ee08CfK4YuKmuL54V9MLhI1kpzxfOJ/63LzmZzDg==} + engines: {node: '>=14'} + dependencies: + '@types/sarif': 2.1.6 + fs-extra: 10.1.0 + dev: false + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: false + + /oas-kit-common@1.0.8: + resolution: {integrity: sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==} + dependencies: + fast-safe-stringify: 2.1.1 + dev: false + + /oas-linter@3.2.2: + resolution: {integrity: sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==} + dependencies: + '@exodus/schemasafe': 1.3.0 + should: 13.2.3 + yaml: 1.10.2 + dev: false + + /oas-resolver@2.5.6: + resolution: {integrity: sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==} + hasBin: true + dependencies: + node-fetch-h2: 2.3.0 + oas-kit-common: 1.0.8 + reftools: 1.1.9 + yaml: 1.10.2 + yargs: 17.3.1 + dev: false + + /oas-schema-walker@1.1.5: + resolution: {integrity: sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==} + dev: false + + /oas-validator@5.0.8: + resolution: {integrity: sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==} + dependencies: + call-me-maybe: 1.0.2 + oas-kit-common: 1.0.8 + oas-linter: 3.2.2 + oas-resolver: 2.5.6 + oas-schema-walker: 1.1.5 + reftools: 1.1.9 + should: 13.2.3 + yaml: 1.10.2 + dev: false + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: false + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: false + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: false + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: false + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: false + + /openapi-sampler@1.3.1: + resolution: {integrity: sha512-Ert9mvc2tLPmmInwSyGZS+v4Ogu9/YoZuq9oP3EdUklg2cad6+IGndP9yqJJwbgdXwZibiq5fpv6vYujchdJFg==} + dependencies: + '@types/json-schema': 7.0.14 + json-pointer: 0.6.2 + dev: false + + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: false + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: false + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: false + + /perfect-scrollbar@1.5.5: + resolution: {integrity: sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g==} + dev: false + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: false + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: false + + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: false + + /polished@4.2.2: + resolution: {integrity: sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==} + engines: {node: '>=10'} + dependencies: + '@babel/runtime': 7.23.2 + dev: false + + /pony-cause@1.1.1: + resolution: {integrity: sha512-PxkIc/2ZpLiEzQXu5YRDOUgBlfGYBY8156HY5ZcRAwwonMk5W/MrJP2LLkG/hF7GEQzaHo2aS7ho6ZLCOvf+6g==} + engines: {node: '>=12.0.0'} + dev: false + + /portfinder@1.0.32: + resolution: {integrity: sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==} + engines: {node: '>= 0.12.0'} + dependencies: + async: 2.6.4 + debug: 3.2.7 + mkdirp: 0.5.6 + transitivePeerDependencies: + - supports-color + dev: false + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: false + + /printable-characters@1.0.42: + resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} + dev: false + + /prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + dev: false + + /prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + dev: false + + /punycode@2.1.1: + resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + engines: {node: '>=6'} + dev: false + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: false + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /react-dom@17.0.2(react@17.0.2): + resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} + peerDependencies: + react: 17.0.2 + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react: 17.0.2 + scheduler: 0.20.2 + dev: false + + /react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + dev: false + + /react-tabs@3.2.3(react@17.0.2): + resolution: {integrity: sha512-jx325RhRVnS9DdFbeF511z0T0WEqEoMl1uCE3LoZ6VaZZm7ytatxbum0B8bCTmaiV0KsU+4TtLGTGevCic7SWg==} + peerDependencies: + react: ^16.3.0 || ^17.0.0-0 + dependencies: + clsx: 1.2.1 + prop-types: 15.8.1 + react: 17.0.2 + dev: false + + /react@17.0.2: + resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + dev: false + + /readable-stream@3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: false + + /redoc@2.0.0(core-js@3.33.1)(mobx@6.10.2)(react-dom@17.0.2)(react@17.0.2)(styled-components@5.3.11)(webpack@5.89.0): + resolution: {integrity: sha512-rU8iLdAkT89ywOkYk66Mr+IofqaMASlRvTew0dJvopCORMIPUcPMxjlJbJNC6wsn2vvMnpUFLQ/0ISDWn9BWag==} + engines: {node: '>=6.9', npm: '>=3.0.0'} + peerDependencies: + core-js: ^3.1.4 + mobx: ^6.0.4 + react: ^16.8.4 || ^17.0.0 + react-dom: ^16.8.4 || ^17.0.0 + styled-components: ^4.1.1 || ^5.1.1 + dependencies: + '@redocly/openapi-core': 1.4.0 + call-me-maybe: 1.0.2 + classnames: 2.3.2 + core-js: 3.33.1 + decko: 1.2.0 + dompurify: 2.4.7 + eventemitter3: 4.0.7 + fast-safe-stringify: 2.1.1 + json-pointer: 0.6.2 + lunr: 2.3.9 + mark.js: 8.11.1 + marked: 4.3.0 + mobx: 6.10.2 + mobx-react: 7.6.0(mobx@6.10.2)(react-dom@17.0.2)(react@17.0.2) + openapi-sampler: 1.3.1 + path-browserify: 1.0.1 + perfect-scrollbar: 1.5.5 + polished: 4.2.2 + prismjs: 1.29.0 + prop-types: 15.8.1 + react: 17.0.2 + react-dom: 17.0.2(react@17.0.2) + react-tabs: 3.2.3(react@17.0.2) + slugify: 1.4.7 + stickyfill: 1.1.1 + style-loader: 3.3.3(webpack@5.89.0) + styled-components: 5.3.11(@babel/core@7.23.2)(react-dom@17.0.2)(react-is@16.13.1)(react@17.0.2) + swagger2openapi: 7.0.8 + url-template: 2.0.8 + yaml: 2.1.3 + transitivePeerDependencies: + - encoding + - react-native + - webpack + dev: false + + /reftools@1.1.9: + resolution: {integrity: sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==} + dev: false + + /regenerator-runtime@0.14.0: + resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} + dev: false + + /regexp.prototype.flags@1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + set-function-name: 2.0.1 + dev: false + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: false + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: false + + /reserved@0.1.2: + resolution: {integrity: sha512-/qO54MWj5L8WCBP9/UNe2iefJc+L9yETbH32xO/ft/EYPOTCR5k+azvDUgdCOKwZH8hXwPd0b8XBL78Nn2U69g==} + engines: {node: '>=0.8'} + dev: false + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: false + + /rollup@2.79.1: + resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: false + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: false + + /safe-array-concat@1.0.1: + resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: false + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-regex: 1.1.4 + dev: false + + /safe-stable-stringify@1.1.1: + resolution: {integrity: sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==} + dev: false + + /scheduler@0.20.2: + resolution: {integrity: sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + dev: false + + /schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.14 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + dev: false + + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: false + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: false + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + + /serialize-javascript@6.0.1: + resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} + dependencies: + randombytes: 2.1.0 + dev: false + + /set-function-length@1.1.1: + resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: false + + /set-function-name@2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.1 + dev: false + + /shallowequal@1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + dev: false + + /should-equal@2.0.0: + resolution: {integrity: sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==} + dependencies: + should-type: 1.4.0 + dev: false + + /should-format@3.0.3: + resolution: {integrity: sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==} + dependencies: + should-type: 1.4.0 + should-type-adaptors: 1.1.0 + dev: false + + /should-type-adaptors@1.1.0: + resolution: {integrity: sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==} + dependencies: + should-type: 1.4.0 + should-util: 1.0.1 + dev: false + + /should-type@1.4.0: + resolution: {integrity: sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==} + dev: false + + /should-util@1.0.1: + resolution: {integrity: sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==} + dev: false + + /should@13.2.3: + resolution: {integrity: sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==} + dependencies: + should-equal: 2.0.0 + should-format: 3.0.3 + should-type: 1.4.0 + should-type-adaptors: 1.1.0 + should-util: 1.0.1 + dev: false + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 + dev: false + + /simple-eval@1.0.0: + resolution: {integrity: sha512-kpKJR+bqTscgC0xuAl2xHN6bB12lHjC2DCUfqjAx19bQyO3R2EVLOurm3H9AUltv/uFVcSCVNc6faegR+8NYLw==} + engines: {node: '>=12'} + dependencies: + jsep: 1.3.8 + dev: false + + /simple-websocket@9.1.0: + resolution: {integrity: sha512-8MJPnjRN6A8UCp1I+H/dSFyjwJhp6wta4hsVRhjf8w9qBHRzxYt14RaOcjvQnhD1N4yKOddEjflwMnQM4VtXjQ==} + dependencies: + debug: 4.3.4(supports-color@5.5.0) + queue-microtask: 1.2.3 + randombytes: 2.1.0 + readable-stream: 3.6.0 + ws: 7.5.8 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + + /slugify@1.4.7: + resolution: {integrity: sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==} + engines: {node: '>=8.0.0'} + dev: false + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: false + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: false + + /sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + dev: false + + /stacktracey@2.1.8: + resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} + dependencies: + as-table: 1.0.55 + get-source: 2.0.12 + dev: false + + /stickyfill@1.1.1: + resolution: {integrity: sha512-GCp7vHAfpao+Qh/3Flh9DXEJ/qSi0KJwJw6zYlZOtRYXWUIpMM6mC2rIep/dK8RQqwW0KxGJIllmjPIBOGN8AA==} + dev: false + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: false + + /string.prototype.trim@1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: false + + /string.prototype.trimend@1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: false + + /string.prototype.trimstart@1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: false + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: false + + /style-loader@3.3.3(webpack@5.89.0): + resolution: {integrity: sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + webpack: 5.89.0 + dev: false + + /styled-components@5.3.11(@babel/core@7.23.2)(react-dom@17.0.2)(react-is@16.13.1)(react@17.0.2): + resolution: {integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==} + engines: {node: '>=10'} + peerDependencies: + react: '>= 16.8.0' + react-dom: '>= 16.8.0' + react-is: '>= 16.8.0' + dependencies: + '@babel/helper-module-imports': 7.22.15 + '@babel/traverse': 7.23.2(supports-color@5.5.0) + '@emotion/is-prop-valid': 1.2.1 + '@emotion/stylis': 0.8.5 + '@emotion/unitless': 0.7.5 + babel-plugin-styled-components: 2.1.4(@babel/core@7.23.2)(styled-components@5.3.11) + css-to-react-native: 3.2.0 + hoist-non-react-statics: 3.3.2 + react: 17.0.2 + react-dom: 17.0.2(react@17.0.2) + react-is: 16.13.1 + shallowequal: 1.1.0 + supports-color: 5.5.0 + transitivePeerDependencies: + - '@babel/core' + dev: false + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: false + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: false + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: false + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: false + + /swagger2openapi@7.0.8: + resolution: {integrity: sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==} + hasBin: true + dependencies: + call-me-maybe: 1.0.2 + node-fetch: 2.6.7 + node-fetch-h2: 2.3.0 + node-readfiles: 0.2.0 + oas-kit-common: 1.0.8 + oas-resolver: 2.5.6 + oas-schema-walker: 1.1.5 + oas-validator: 5.0.8 + reftools: 1.1.9 + yaml: 1.10.2 + yargs: 17.3.1 + transitivePeerDependencies: + - encoding + dev: false + + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: false + + /terser-webpack-plugin@5.3.9(webpack@5.89.0): + resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.20 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.23.0 + webpack: 5.89.0 + dev: false + + /terser@5.23.0: + resolution: {integrity: sha512-Iyy83LN0uX9ZZLCX4Qbu5JiHiWjOCTwrmM9InWOzVeM++KNWEsqV4YgN9U9E8AlohQ6Gs42ztczlWOG/lwDAMA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.5 + acorn: 8.11.2 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: false + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: false + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: false + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: false + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: false + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: false + + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: false + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: false + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: false + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: false + + /uglify-js@3.16.0: + resolution: {integrity: sha512-FEikl6bR30n0T3amyBh3LoiBdqHRy/f4H80+My34HOesOKyHfOsxAPAxOoqC0JUnC1amnO0IwkYC3sko51caSw==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: false + optional: true + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.5 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: false + + /universalify@2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + dev: false + + /update-browserslist-db@1.0.13(browserslist@4.22.1): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.22.1 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: false + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.1.1 + dev: false + + /urijs@1.19.11: + resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==} + dev: false + + /url-template@2.0.8: + resolution: {integrity: sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==} + dev: false + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + + /utility-types@3.10.0: + resolution: {integrity: sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==} + engines: {node: '>= 4'} + dev: false + + /validate-npm-package-name@3.0.0: + resolution: {integrity: sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==} + dependencies: + builtins: 1.0.3 + dev: false + + /watchpack@2.4.0: + resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} + engines: {node: '>=10.13.0'} + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + dev: false + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: false + + /webpack@5.89.0: + resolution: {integrity: sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.6 + '@types/estree': 1.0.3 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/wasm-edit': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + acorn: 8.11.2 + acorn-import-assertions: 1.9.0(acorn@8.11.2) + browserslist: 4.22.1 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.15.0 + es-module-lexer: 1.3.1 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.9(webpack@5.89.0) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: false + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: false + + /which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: false + + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: false + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: false + + /ws@7.5.8: + resolution: {integrity: sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: false + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: false + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false + + /yaml-ast-parser@0.0.43: + resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==} + dev: false + + /yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: false + + /yaml@2.1.3: + resolution: {integrity: sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==} + engines: {node: '>= 14'} + dev: false + + /yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: false + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: false + + /yargs@17.0.1: + resolution: {integrity: sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==} + engines: {node: '>=12'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + dev: false + + /yargs@17.3.1: + resolution: {integrity: sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==} + engines: {node: '>=12'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: false diff --git a/router/mgmtapi/BUILD.bazel b/router/mgmtapi/BUILD.bazel index c57c59a4e..887c65731 100644 --- a/router/mgmtapi/BUILD.bazel +++ b/router/mgmtapi/BUILD.bazel @@ -1,8 +1,7 @@ load("//tools/lint:go.bzl", "go_library", "go_test") -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_build_docs") -load("//private/mgmtapi:api.bzl", "openapi_generate_go") +load("//private/mgmtapi:api.bzl", "openapi_docs", "openapi_generate_go") -openapi_build_docs( +openapi_docs( name = "doc", src = "//spec:router", out = "index.html", diff --git a/rules_openapi/defs.bzl b/rules_openapi/defs.bzl index 8dfffe5d7..76163c17e 100644 --- a/rules_openapi/defs.bzl +++ b/rules_openapi/defs.bzl @@ -1,25 +1,4 @@ load("//rules_openapi/internal:generate.bzl", _openapi_generate_go = "openapi_generate_go") -load("//rules_openapi/internal:bundle.bzl", _openapi_bundle = "openapi_bundle") -load("//rules_openapi/internal:docs.bzl", _openapi_build_docs = "openapi_build_docs") - -def openapi_bundle( - name, - srcs, - entrypoint, - visibility = None): - _openapi_bundle( - name = name + "-no-header", - out = name + "-no-header.bzl.gen.yml", - srcs = srcs, - entrypoint = entrypoint, - ) - native.genrule( - name = name, - srcs = [name + "-no-header"], - outs = [name + ".bzl.gen.yml"], - cmd = "(echo '# GENERATED FILE DO NOT EDIT'; cat $<) > $@", - visibility = visibility, - ) def openapi_generate_go( name, @@ -28,15 +7,3 @@ def openapi_generate_go( name = name, **kwargs ) - -def openapi_build_docs( - name, - src, - out, - **kwargs): - _openapi_build_docs( - name = name, - src = src, - out = out, - **kwargs - ) diff --git a/rules_openapi/dependencies.bzl b/rules_openapi/dependencies.bzl deleted file mode 100644 index 47a02d3b3..000000000 --- a/rules_openapi/dependencies.bzl +++ /dev/null @@ -1,10 +0,0 @@ -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") - -def rules_openapi_dependencies(): - maybe( - http_archive, - name = "build_bazel_rules_nodejs", - sha256 = "b32a4713b45095e9e1921a7fcb1adf584bc05959f3336e7351bcf77f015a2d7c", - urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/4.1.0/rules_nodejs-4.1.0.tar.gz"], - ) diff --git a/rules_openapi/install.bzl b/rules_openapi/install.bzl deleted file mode 100644 index 69bdff302..000000000 --- a/rules_openapi/install.bzl +++ /dev/null @@ -1,20 +0,0 @@ -load( - "@build_bazel_rules_nodejs//:index.bzl", - "node_repositories", - "yarn_install", -) - -PACKAGE_JSON = "@com_github_scionproto_scion//rules_openapi/tools:package.json" - -def rules_openapi_install_yarn_dependencies(): - node_repositories( - package_json = [PACKAGE_JSON], - ) - yarn_install( - name = "rules_openapi_npm", - # Opt out of directory artifacts, we rely on ts_library which needs - # to see labels for all third-party files. - exports_directories_only = False, - package_json = PACKAGE_JSON, - yarn_lock = "@com_github_scionproto_scion//rules_openapi/tools:yarn.lock", - ) diff --git a/rules_openapi/internal/BUILD.bazel b/rules_openapi/internal/BUILD.bazel index feb4d1403..1c834b4e4 100644 --- a/rules_openapi/internal/BUILD.bazel +++ b/rules_openapi/internal/BUILD.bazel @@ -1,13 +1,8 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -exports_files(["header.sh"]) - bzl_library( name = "rules_openapi_internal", srcs = [ - "bundle.bzl", - "docs.bzl", "generate.bzl", - "header.bzl", ], ) diff --git a/rules_openapi/internal/bundle.bzl b/rules_openapi/internal/bundle.bzl deleted file mode 100644 index f0bd3e097..000000000 --- a/rules_openapi/internal/bundle.bzl +++ /dev/null @@ -1,50 +0,0 @@ -load("@bazel_skylib//lib:shell.bzl", "shell") - -def _openapi_bundle_impl(ctx): - if ctx.outputs.out: - out_file = ctx.outputs.out - else: - out_file = ctx.actions.declare_file(ctx.label.name + ".bzl.gen.yml") - - cmd = "{bin} bundle --output {out} {entrypoint}".format( - bin = ctx.executable._openapi_cli.path, - out = shell.quote(out_file.path), - entrypoint = shell.quote(ctx.file.entrypoint.path), - ) - - ctx.actions.run_shell( - outputs = [out_file], - inputs = [ctx.file.entrypoint] + ctx.files.srcs, - tools = [ctx.executable._openapi_cli], - command = cmd, - mnemonic = "OpenAPIBundle", - use_default_shell_env = True, - ) - return [DefaultInfo( - files = depset([out_file]), - )] - -openapi_bundle = rule( - implementation = _openapi_bundle_impl, - doc = "This rule can be used to bundle open API specification files.", - attrs = { - "srcs": attr.label_list( - doc = "All files that are referenced in the entrypoint file", - allow_files = [".yml"], - ), - "out": attr.output( - doc = "The bundled open API specification file", - mandatory = False, - ), - "entrypoint": attr.label( - doc = "The main source to generate files from", - allow_single_file = [".yml"], - mandatory = True, - ), - "_openapi_cli": attr.label( - default = "@rules_openapi_npm//@redocly/cli/bin:openapi", - executable = True, - cfg = "target", - ), - }, -) diff --git a/rules_openapi/internal/docs.bzl b/rules_openapi/internal/docs.bzl deleted file mode 100644 index 5f613b2ba..000000000 --- a/rules_openapi/internal/docs.bzl +++ /dev/null @@ -1,39 +0,0 @@ -load("@bazel_skylib//lib:shell.bzl", "shell") - -def _openapi_build_docs_impl(ctx): - cmd = "{bin} build-docs --output {out} {src}".format( - bin = ctx.executable._openapi_cli.path, - out = shell.quote(ctx.outputs.out.path), - src = shell.quote(ctx.file.src.path), - ) - - ctx.actions.run_shell( - outputs = [ctx.outputs.out], - inputs = [ctx.file.src], - tools = [ctx.executable._openapi_cli], - command = cmd, - mnemonic = "OpenAPIBuildDocs", - use_default_shell_env = True, - ) - return [DefaultInfo( - files = depset([ctx.outputs.out]), - )] - -openapi_build_docs = rule( - implementation = _openapi_build_docs_impl, - doc = "This rule can be used to create API documentation as a single, zero-dependency HTML file.", - attrs = { - "src": attr.label( - doc = "The API definition file", - allow_single_file = [".yml"], - ), - "out": attr.output( - doc = "The output HTML file generated by this rule", - ), - "_openapi_cli": attr.label( - default = "@rules_openapi_npm//@redocly/cli/bin:openapi", - executable = True, - cfg = "target", - ), - }, -) diff --git a/rules_openapi/tools/BUILD.bazel b/rules_openapi/tools/BUILD.bazel deleted file mode 100644 index ac5cea622..000000000 --- a/rules_openapi/tools/BUILD.bazel +++ /dev/null @@ -1,6 +0,0 @@ -exports_files( - [ - "package.json", - "yarn.lock", - ], -) diff --git a/rules_openapi/tools/README.md b/rules_openapi/tools/README.md deleted file mode 100644 index 4cea1e2e3..000000000 --- a/rules_openapi/tools/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Managing yarn dependencies with bazel - -To update the YARN dependencies in this directory: - -1. `cd` into the directory. -1. run your yarn command: - - - bazel run @nodejs//:yarn upgrade - - bazel run @nodejs//:yarn install ... - - etc. see [yarn docs](https://classic.yarnpkg.com/en/docs/usage/) for more details. - -To list bazel targets from this specific yarn module: `bazel query @rules_openapi_npm//...` - -More information can be found in [rules_nodejs -docs](https://docs.aspect.dev/bazelbuild/rules_nodejs/4.0.0/docs/). diff --git a/rules_openapi/tools/package.json b/rules_openapi/tools/package.json deleted file mode 100644 index ae5fcb2a0..000000000 --- a/rules_openapi/tools/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": { - "@redocly/cli": "^1.0.0-beta.123", - "@stoplight/spectral-cli": "^6.6.0", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2" - } -} diff --git a/rules_openapi/tools/yarn.lock b/rules_openapi/tools/yarn.lock deleted file mode 100644 index b16f2846f..000000000 --- a/rules_openapi/tools/yarn.lock +++ /dev/null @@ -1,2859 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@asyncapi/specs@^4.1.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@asyncapi/specs/-/specs-4.2.0.tgz#33003051aa50785e3480c18ac7d9afbc8e68434d" - integrity sha512-V9bFzUGNXrpsyennEXNZaPvdoFYYoeUYYAGiQVYsGsUsF/IL/G40NpE9u6nPeXGj8sZgjKlUG6iP39T0DYtSlQ== - dependencies: - "@types/json-schema" "^7.0.11" - -"@babel/code-frame@^7.18.6", "@babel/code-frame@^7.21.4": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" - integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/generator@^7.21.4": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.4.tgz#64a94b7448989f421f919d5239ef553b37bb26bc" - integrity sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA== - dependencies: - "@babel/types" "^7.21.4" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/helper-annotate-as-pure@^7.16.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" - integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== - -"@babel/helper-function-name@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" - integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== - dependencies: - "@babel/template" "^7.20.7" - "@babel/types" "^7.21.0" - -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.16.0": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz#ac88b2f76093637489e718a90cec6cf8a9b029af" - integrity sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg== - dependencies: - "@babel/types" "^7.21.4" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== - -"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.20.7", "@babel/parser@^7.21.4": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.4.tgz#94003fdfc520bbe2875d4ae557b43ddb6d880f17" - integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw== - -"@babel/runtime@^7.17.8": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" - integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== - dependencies: - regenerator-runtime "^0.13.11" - -"@babel/template@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" - integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - -"@babel/traverse@^7.4.5": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.4.tgz#a836aca7b116634e97a6ed99976236b3282c9d36" - integrity sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q== - dependencies: - "@babel/code-frame" "^7.21.4" - "@babel/generator" "^7.21.4" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.21.4" - "@babel/types" "^7.21.4" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.18.6", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.4": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.4.tgz#2d5d6bb7908699b3b416409ffd3b5daa25b030d4" - integrity sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA== - dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" - to-fast-properties "^2.0.0" - -"@emotion/is-prop-valid@^0.8.8": - version "0.8.8" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" - integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== - dependencies: - "@emotion/memoize" "0.7.4" - -"@emotion/memoize@0.7.4": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" - integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== - -"@emotion/stylis@^0.8.4": - version "0.8.5" - resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" - integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== - -"@emotion/unitless@^0.7.4": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" - integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== - -"@exodus/schemasafe@^1.0.0-rc.2": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.0.0.tgz#f44e252665b1a6bdef0d686e22af3599a6f0a095" - integrity sha512-2cyupPIZI69HQxEAPllLXBjQp4njDKkOjYRCYxvMZe3/LY9pp9fBM3Tb1wiFAdP6Emo4v3OEbCLGj6u73Q5KLw== - -"@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@1.4.14": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.18" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" - integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== - dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" - -"@jsep-plugin/regex@^1.0.1": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.3.tgz#3aeaa2e5fa45d89de116aeafbfa41c95935b7f6d" - integrity sha512-XfZgry4DwEZvSFtS/6Y+R48D7qJYJK6R9/yJFyUFHCIUMEEHuJ4X95TDgJp5QkmzfLYvapMPzskV5HpIDrREug== - -"@jsep-plugin/ternary@^1.0.2": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@jsep-plugin/ternary/-/ternary-1.1.3.tgz#9ac0b752b9e99f55d23bfcb32cf08c5c2c03ce67" - integrity sha512-qtLGzCNzPVJ3kdH6/zoLWDPjauHIKiLSBAR71Wa0+PWvGA8wODUQvRgxtpUA5YqAYL3CQ8S4qXhd/9WuWTZirg== - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@redocly/ajv@^8.11.0": - version "8.11.0" - resolved "https://registry.yarnpkg.com/@redocly/ajv/-/ajv-8.11.0.tgz#2fad322888dc0113af026e08fceb3e71aae495ae" - integrity sha512-9GWx27t7xWhDIR02PA18nzBdLcKQRgc46xNQvjFkrYk4UOmvKhJ/dawwiX0cCOeetN5LcaaiqQbVOWYK62SGHw== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -"@redocly/cli@^1.0.0-beta.123": - version "1.0.0-beta.125" - resolved "https://registry.yarnpkg.com/@redocly/cli/-/cli-1.0.0-beta.125.tgz#3b107579193572289b264fb12edc2127e3175dbe" - integrity sha512-3n5wtCux2vtWdxPvLs5nvbiYiEz+gkAPs/1kC/df7tzBOZ3zld6onrwuBjhMKtzJbJ1B3i1yzrfJz0mMmoNrtQ== - dependencies: - "@redocly/openapi-core" "1.0.0-beta.125" - assert-node-version "^1.0.3" - chokidar "^3.5.1" - colorette "^1.2.0" - glob "^7.1.6" - glob-promise "^3.4.0" - handlebars "^4.7.6" - mobx "^6.3.2" - portfinder "^1.0.26" - react "^17.0.1" - react-dom "^17.0.1" - redoc "~2.0.0" - simple-websocket "^9.0.0" - styled-components "5.3.3" - yargs "17.0.1" - -"@redocly/openapi-core@1.0.0-beta.125", "@redocly/openapi-core@^1.0.0-beta.104": - version "1.0.0-beta.125" - resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.0.0-beta.125.tgz#a87b7cbbbd1cef2206bcc2c6c7b498f07378466b" - integrity sha512-3kpvIP6nzqrXl59BXovm1aGcbqSJv37t9kjFxuEvsGZzVSUC8rGZl4tNEZ3Qfm+mbPs+XWDi/U43kf/u3bUCpw== - dependencies: - "@redocly/ajv" "^8.11.0" - "@types/node" "^14.11.8" - colorette "^1.2.0" - js-levenshtein "^1.1.6" - js-yaml "^4.1.0" - lodash.isequal "^4.5.0" - minimatch "^5.0.1" - node-fetch "^2.6.1" - pluralize "^8.0.0" - yaml-ast-parser "0.0.43" - -"@rollup/plugin-commonjs@~22.0.2": - version "22.0.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz#ee8ca8415cda30d383b4096aad5222435b4b69b6" - integrity sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - commondir "^1.0.1" - estree-walker "^2.0.1" - glob "^7.1.6" - is-reference "^1.2.1" - magic-string "^0.25.7" - resolve "^1.17.0" - -"@rollup/pluginutils@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" - integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== - dependencies: - "@types/estree" "0.0.39" - estree-walker "^1.0.1" - picomatch "^2.2.2" - -"@stoplight/better-ajv-errors@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.3.tgz#d74a5c4da5d786c17188d7f4edec505f089885fa" - integrity sha512-0p9uXkuB22qGdNfy3VeEhxkU5uwvp/KrBTAbrLBURv6ilxIVwanKwjMc41lQfIVgPGcOkmLbTolfFrSsueu7zA== - dependencies: - jsonpointer "^5.0.0" - leven "^3.1.0" - -"@stoplight/json-ref-readers@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@stoplight/json-ref-readers/-/json-ref-readers-1.2.2.tgz#e5992bae597f228f988f362a4c0304c03a92008b" - integrity sha512-nty0tHUq2f1IKuFYsLM4CXLZGHdMn+X/IwEUIpeSOXt0QjMUbL0Em57iJUDzz+2MkWG83smIigNZ3fauGjqgdQ== - dependencies: - node-fetch "^2.6.0" - tslib "^1.14.1" - -"@stoplight/json-ref-resolver@~3.1.4", "@stoplight/json-ref-resolver@~3.1.5": - version "3.1.5" - resolved "https://registry.yarnpkg.com/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.5.tgz#e4454a69027559ef3f7272941e99310a19dc8fdf" - integrity sha512-uaKLITor7UF+JBtI84zs3aOWM0L79zp7w9TrBTwPtx5SLbaQQ4HadDKgX5yhFOLMApLdhwhiftF4c0GFanOxGg== - dependencies: - "@stoplight/json" "^3.17.0" - "@stoplight/path" "^1.3.2" - "@stoplight/types" "^12.3.0 || ^13.0.0" - "@types/urijs" "^1.19.19" - dependency-graph "~0.11.0" - fast-memoize "^2.5.2" - immer "^9.0.6" - lodash "^4.17.21" - tslib "^2.3.1" - urijs "^1.19.11" - -"@stoplight/json@^3.17.0", "@stoplight/json@^3.17.1", "@stoplight/json@~3.20.1": - version "3.20.2" - resolved "https://registry.yarnpkg.com/@stoplight/json/-/json-3.20.2.tgz#466ba5c6381cfd141f1726439442fbd579804c8e" - integrity sha512-e3Eb/DdLSpJVAsxAG1jKSnl4TVZLl2pH8KsJBWKf5GPCeI58Eo0ZpRTX3HcZ0gBaHWH6CnEHJkCRCONhoFbDIA== - dependencies: - "@stoplight/ordered-object-literal" "^1.0.3" - "@stoplight/path" "^1.3.2" - "@stoplight/types" "^13.6.0" - jsonc-parser "~2.2.1" - lodash "^4.17.21" - safe-stable-stringify "^1.1" - -"@stoplight/ordered-object-literal@^1.0.1", "@stoplight/ordered-object-literal@^1.0.3", "@stoplight/ordered-object-literal@~1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@stoplight/ordered-object-literal/-/ordered-object-literal-1.0.4.tgz#c8bb2698ab229f31e31a16dd1852c867c1f2f2ed" - integrity sha512-OF8uib1jjDs5/cCU+iOVy+GJjU3X7vk/qJIkIJFqwmlJKrrtijFmqwbu8XToXrwTYLQTP+Hebws5gtZEmk9jag== - -"@stoplight/path@1.3.2", "@stoplight/path@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@stoplight/path/-/path-1.3.2.tgz#96e591496b72fde0f0cdae01a61d64f065bd9ede" - integrity sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ== - -"@stoplight/spectral-cli@^6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-cli/-/spectral-cli-6.6.0.tgz#6a8cb630bb14408c9ace955ad51fb05049db0fba" - integrity sha512-z46fnrvraaWMio8Y9RYYkLO+XdmtxOWpy5qNJF3CsmWua0FZ4iOTryb5Cm3GkB0wEtqxNUCBUHvoo4hS6Noyqg== - dependencies: - "@stoplight/json" "~3.20.1" - "@stoplight/path" "1.3.2" - "@stoplight/spectral-core" "^1.15.1" - "@stoplight/spectral-parsers" "^1.0.2" - "@stoplight/spectral-ref-resolver" "1.0.2" - "@stoplight/spectral-ruleset-bundler" "^1.4.0" - "@stoplight/spectral-ruleset-migrator" "^1.9.0" - "@stoplight/spectral-rulesets" ">=1" - "@stoplight/spectral-runtime" "^1.1.2" - "@stoplight/types" "^13.6.0" - chalk "4.1.2" - cliui "7.0.4" - eol "0.9.1" - fast-glob "3.2.7" - lodash "~4.17.21" - pony-cause "^1.0.0" - proxy-agent "5.0.0" - stacktracey "^2.1.7" - strip-ansi "6.0" - text-table "0.2" - tslib "^2.3.0" - yargs "17.3.1" - -"@stoplight/spectral-core@>=1", "@stoplight/spectral-core@^1.15.1", "@stoplight/spectral-core@^1.7.0", "@stoplight/spectral-core@^1.8.0", "@stoplight/spectral-core@^1.8.1": - version "1.17.0" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-core/-/spectral-core-1.17.0.tgz#f897871f394e62ab9fdf15119730db5d82fc5e47" - integrity sha512-7D9og+iX2bCJMGPY7cvt2YdevFGDeSI7S2jPo7HWeGGitkef1FDSQ9AEapdwmCYvOJ7ztUlQdCCLTOb6Aani8w== - dependencies: - "@stoplight/better-ajv-errors" "1.0.3" - "@stoplight/json" "~3.20.1" - "@stoplight/path" "1.3.2" - "@stoplight/spectral-parsers" "^1.0.0" - "@stoplight/spectral-ref-resolver" "^1.0.0" - "@stoplight/spectral-runtime" "^1.0.0" - "@stoplight/types" "~13.6.0" - "@types/es-aggregate-error" "^1.0.2" - "@types/json-schema" "^7.0.11" - ajv "^8.6.0" - ajv-errors "~3.0.0" - ajv-formats "~2.1.0" - es-aggregate-error "^1.0.7" - jsonpath-plus "7.1.0" - lodash "~4.17.21" - lodash.topath "^4.5.2" - minimatch "3.1.2" - nimma "0.2.2" - pony-cause "^1.0.0" - simple-eval "1.0.0" - tslib "^2.3.0" - -"@stoplight/spectral-formats@>=1", "@stoplight/spectral-formats@^1.0.0", "@stoplight/spectral-formats@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-formats/-/spectral-formats-1.5.0.tgz#222dd1e1302c54ba3219b8223b299d9515fed3e3" - integrity sha512-VskkdU3qBSvI1dfJ79ysjvTssfNlbA6wrf/XkXK6iTyjfIVqOAWVtjypTb2U95tN/X8IjIBBhNWtZ4tNVZilrA== - dependencies: - "@stoplight/json" "^3.17.0" - "@stoplight/spectral-core" "^1.8.0" - "@types/json-schema" "^7.0.7" - tslib "^2.3.1" - -"@stoplight/spectral-functions@>=1", "@stoplight/spectral-functions@^1.0.0", "@stoplight/spectral-functions@^1.5.1": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-functions/-/spectral-functions-1.7.2.tgz#96ddc5dc2b093fba41a902a0ef374300f861f58f" - integrity sha512-f+61/FtIkQeIo+a269CeaeqjpyRsgDyIk6DGr7iS4hyuk1PPk7Uf6MNRDs9FEIBh7CpdEJ+HSHbMLwgpymWTIw== - dependencies: - "@stoplight/better-ajv-errors" "1.0.3" - "@stoplight/json" "^3.17.1" - "@stoplight/spectral-core" "^1.7.0" - "@stoplight/spectral-formats" "^1.0.0" - "@stoplight/spectral-runtime" "^1.1.0" - ajv "^8.6.3" - ajv-draft-04 "~1.0.0" - ajv-errors "~3.0.0" - ajv-formats "~2.1.0" - lodash "~4.17.21" - tslib "^2.3.0" - -"@stoplight/spectral-parsers@>=1", "@stoplight/spectral-parsers@^1.0.0", "@stoplight/spectral-parsers@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-parsers/-/spectral-parsers-1.0.2.tgz#2411ff5499ad351414ed8e0ea32f1f24efebb49c" - integrity sha512-ZQXknJ+BM5Re4Opj4cgVlHgG2qyOk/wznKJq3Vf1qsBEg2CNzN0pJmSB0deRqW0kArqm44qpb8c+cz3F2rgMtw== - dependencies: - "@stoplight/json" "~3.20.1" - "@stoplight/types" "^13.6.0" - "@stoplight/yaml" "~4.2.3" - tslib "^2.3.1" - -"@stoplight/spectral-ref-resolver@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.2.tgz#acae9511e17a4da97ecca48c005a4475d24fe76b" - integrity sha512-ah6NIB/O1EdEaEu89So3LmtbKRXPVnSElgQ7oBRE9S4/VOedSqyXn+qqMd40tGnO2CsKgZaFUYXdSEHOshpHYw== - dependencies: - "@stoplight/json-ref-readers" "1.2.2" - "@stoplight/json-ref-resolver" "~3.1.4" - "@stoplight/spectral-runtime" "^1.1.2" - dependency-graph "0.11.0" - tslib "^2.3.1" - -"@stoplight/spectral-ref-resolver@>=1", "@stoplight/spectral-ref-resolver@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.3.tgz#6754f212c27723af7a438129d47f941184a21edd" - integrity sha512-pj+bH4SH8hcWlnV787WD7P0/En7LA3EfZMvG1JUGMW/7bFd9AaZZXNkh5j0ve8qnPlwP8F4SH/2Cnr1tXOXCVw== - dependencies: - "@stoplight/json-ref-readers" "1.2.2" - "@stoplight/json-ref-resolver" "~3.1.5" - "@stoplight/spectral-runtime" "^1.1.2" - dependency-graph "0.11.0" - tslib "^2.3.1" - -"@stoplight/spectral-ruleset-bundler@^1.4.0": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.5.1.tgz#52031f9e2b118a24bd0f0f66c30fe8b1afec7e0b" - integrity sha512-gvlBXkyxLBNdslN/5HEYvCqMr0dvKQwJbbJCKbOvvRTZhhPVzmLb7yavWXjOnRhYn6IAhGAs7u4yhxn7cX/FtQ== - dependencies: - "@rollup/plugin-commonjs" "~22.0.2" - "@stoplight/path" "1.3.2" - "@stoplight/spectral-core" ">=1" - "@stoplight/spectral-formats" ">=1" - "@stoplight/spectral-functions" ">=1" - "@stoplight/spectral-parsers" ">=1" - "@stoplight/spectral-ref-resolver" ">=1" - "@stoplight/spectral-ruleset-migrator" "^1.7.4" - "@stoplight/spectral-rulesets" ">=1" - "@stoplight/spectral-runtime" "^1.1.0" - "@stoplight/types" "^13.6.0" - "@types/node" "*" - pony-cause "1.1.1" - rollup "~2.79.0" - tslib "^2.3.1" - validate-npm-package-name "3.0.0" - -"@stoplight/spectral-ruleset-migrator@^1.7.4", "@stoplight/spectral-ruleset-migrator@^1.9.0": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-ruleset-migrator/-/spectral-ruleset-migrator-1.9.2.tgz#6865273880cbee6b79f68b452cc0632e0205496b" - integrity sha512-FbXsPFt+nikggCF1x+kfaNXpE7Ol/0Um1eR0S1/mNyf/L5R0RBnyqZLvJwC6cU6O49CLAjYy7fCbxgrjNcZvbg== - dependencies: - "@stoplight/json" "~3.20.1" - "@stoplight/ordered-object-literal" "~1.0.4" - "@stoplight/path" "1.3.2" - "@stoplight/spectral-functions" "^1.0.0" - "@stoplight/spectral-runtime" "^1.1.0" - "@stoplight/types" "^13.6.0" - "@stoplight/yaml" "~4.2.3" - "@types/node" "*" - ajv "^8.6.0" - ast-types "0.14.2" - astring "^1.7.5" - reserved "0.1.2" - tslib "^2.3.1" - validate-npm-package-name "3.0.0" - -"@stoplight/spectral-rulesets@>=1": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-rulesets/-/spectral-rulesets-1.15.0.tgz#df0322b725fd3d244662b7cd72431d17f32b83dd" - integrity sha512-xgltt54aQPSKKAxPZ2oCA25X/xmDPVCV1e4qxqH5bw/t7LvDWVusBFUrtcl/5HAJIIgkpxOKXKEc2XRC0ea8HQ== - dependencies: - "@asyncapi/specs" "^4.1.0" - "@stoplight/better-ajv-errors" "1.0.3" - "@stoplight/json" "^3.17.0" - "@stoplight/spectral-core" "^1.8.1" - "@stoplight/spectral-formats" "^1.5.0" - "@stoplight/spectral-functions" "^1.5.1" - "@stoplight/spectral-runtime" "^1.1.1" - "@stoplight/types" "^13.6.0" - "@types/json-schema" "^7.0.7" - ajv "^8.8.2" - ajv-formats "~2.1.0" - json-schema-traverse "^1.0.0" - lodash "~4.17.21" - tslib "^2.3.0" - -"@stoplight/spectral-runtime@^1.0.0", "@stoplight/spectral-runtime@^1.1.0", "@stoplight/spectral-runtime@^1.1.1", "@stoplight/spectral-runtime@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@stoplight/spectral-runtime/-/spectral-runtime-1.1.2.tgz#7315767a09a4a7e5226e997e245bd3eb39561a02" - integrity sha512-fr5zRceXI+hrl82yAVoME+4GvJie8v3wmOe9tU+ZLRRNonizthy8qDi0Z/z4olE+vGreSDcuDOZ7JjRxFW5kTw== - dependencies: - "@stoplight/json" "^3.17.0" - "@stoplight/path" "^1.3.2" - "@stoplight/types" "^12.3.0" - abort-controller "^3.0.0" - lodash "^4.17.21" - node-fetch "^2.6.7" - tslib "^2.3.1" - -"@stoplight/types@^12.3.0": - version "12.5.0" - resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-12.5.0.tgz#ebbeeb8c874de30e4cd9a1a2a6c8d6062c155da0" - integrity sha512-dwqYcDrGmEyUv5TWrDam5TGOxU72ufyQ7hnOIIDdmW5ezOwZaBFoR5XQ9AsH49w7wgvOqB2Bmo799pJPWnpCbg== - dependencies: - "@types/json-schema" "^7.0.4" - utility-types "^3.10.0" - -"@stoplight/types@^12.3.0 || ^13.0.0", "@stoplight/types@^13.0.0", "@stoplight/types@^13.6.0": - version "13.11.0" - resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-13.11.0.tgz#3a1e206770e7d5dd65c0cc9206e68be6913f2bce" - integrity sha512-jGojdysNoYytTDCmGEjxugIRllmZhYxMaOt+NtPRo/ZxjXY9mbQ6kzoNWyFiEDzjTVzYyr32ygJ/ex7/LAhvXw== - dependencies: - "@types/json-schema" "^7.0.4" - utility-types "^3.10.0" - -"@stoplight/types@~13.6.0": - version "13.6.0" - resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-13.6.0.tgz#96c6aaae05858b36f589821cd52c95aa9b205ce7" - integrity sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ== - dependencies: - "@types/json-schema" "^7.0.4" - utility-types "^3.10.0" - -"@stoplight/yaml-ast-parser@0.0.48": - version "0.0.48" - resolved "https://registry.yarnpkg.com/@stoplight/yaml-ast-parser/-/yaml-ast-parser-0.0.48.tgz#442b21f419427acaa8a3106ebc5d73351c407002" - integrity sha512-sV+51I7WYnLJnKPn2EMWgS4EUfoP4iWEbrWwbXsj0MZCB/xOK8j6+C9fntIdOM50kpx45ZLC3s6kwKivWuqvyg== - -"@stoplight/yaml@~4.2.3": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@stoplight/yaml/-/yaml-4.2.3.tgz#d177664fecd6b2fd0d4f264f1078550c30cfd8d1" - integrity sha512-Mx01wjRAR9C7yLMUyYFTfbUf5DimEpHMkRDQ1PKLe9dfNILbgdxyrncsOXM3vCpsQ1Hfj4bPiGl+u4u6e9Akqw== - dependencies: - "@stoplight/ordered-object-literal" "^1.0.1" - "@stoplight/types" "^13.0.0" - "@stoplight/yaml-ast-parser" "0.0.48" - tslib "^2.2.0" - -"@tootallnate/once@1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" - integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== - -"@types/es-aggregate-error@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/es-aggregate-error/-/es-aggregate-error-1.0.2.tgz#a970b4a5bbee95d87aebaa2aa317c846c18429df" - integrity sha512-erqUpFXksaeR2kejKnhnjZjbFxUpGZx4Z7ydNL9ie8tEhXPiZTsLeUDJ6aR1F8j5wWUAtOAQWUqkc7givBJbBA== - dependencies: - "@types/node" "*" - -"@types/estree@*": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" - integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== - -"@types/estree@0.0.39": - version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" - integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== - -"@types/glob@*": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" - integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== - dependencies: - "@types/minimatch" "^5.1.2" - "@types/node" "*" - -"@types/json-schema@^7.0.11", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.7": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== - -"@types/minimatch@^5.1.2": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" - integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== - -"@types/node@*": - version "18.15.11" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" - integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== - -"@types/node@^14.11.8": - version "14.18.42" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.42.tgz#fa39b2dc8e0eba61bdf51c66502f84e23b66e114" - integrity sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg== - -"@types/urijs@^1.19.19": - version "1.19.19" - resolved "https://registry.yarnpkg.com/@types/urijs/-/urijs-1.19.19.tgz#2789369799907fc11e2bc6e3a00f6478c2281b95" - integrity sha512-FDJNkyhmKLw7uEvTxx5tSXfPeQpO0iy73Ry+PmYZJvQy0QIWX8a7kJ4kLWRf+EbTPJEPDSgPXHaM7pzr5lmvCg== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -acorn-walk@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.7.0: - version "8.8.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" - integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== - -agent-base@6, agent-base@^6.0.0, agent-base@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - -ajv-draft-04@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" - integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== - -ajv-errors@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-3.0.0.tgz#e54f299f3a3d30fe144161e5f0d8d51196c527bc" - integrity sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ== - -ajv-formats@~2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv@^8.0.0, ajv@^8.6.0, ajv@^8.6.3, ajv@^8.8.2: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-buffer-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" - integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== - dependencies: - call-bind "^1.0.2" - is-array-buffer "^3.0.1" - -as-table@^1.0.36: - version "1.0.55" - resolved "https://registry.yarnpkg.com/as-table/-/as-table-1.0.55.tgz#dc984da3937745de902cea1d45843c01bdbbec4f" - integrity sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ== - dependencies: - printable-characters "^1.0.42" - -assert-node-version@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/assert-node-version/-/assert-node-version-1.0.3.tgz#caea5d1b6a58dbce59661208df1e1b9e4c580f91" - integrity sha512-XcKBGJ1t0RrCcus9dQX57FER4PTEz/+Tee2jj+EdFIGyw5j8hwDNXZzgRYLQ916twVjSuA47adrZsSxLbpEX9A== - dependencies: - expected-node-version "^1.0.0" - semver "^5.0.3" - -ast-types@0.14.2: - version "0.14.2" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" - integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA== - dependencies: - tslib "^2.0.1" - -ast-types@^0.13.2: - version "0.13.4" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" - integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== - dependencies: - tslib "^2.0.1" - -astring@^1.7.5, astring@^1.8.1: - version "1.8.4" - resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.4.tgz#6d4c5d8de7be2ead9e4a3cc0e2efb8d759378904" - integrity sha512-97a+l2LBU3Op3bBQEff79i/E4jMD2ZLFD8rHx9B6mXyB2uQwhJQYfiDqUwtfjF4QA1F2qs//N6Cw8LetMbQjcw== - -async@^2.6.4: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -"babel-plugin-styled-components@>= 1.12.0": - version "2.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.1.tgz#cd977cc0ff8410d5cbfdd142e42576e9c8794b87" - integrity sha512-c8lJlszObVQPguHkI+akXv8+Jgb9Ccujx0EetL7oIvwU100LxO6XAGe45qry37wUL40a5U9f23SYrivro2XKhA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.0" - "@babel/helper-module-imports" "^7.16.0" - babel-plugin-syntax-jsx "^6.18.0" - lodash "^4.17.21" - picomatch "^2.3.0" - -babel-plugin-syntax-jsx@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - integrity sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -builtins@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -call-me-maybe@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" - integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== - -camelize@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" - integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== - -chalk@4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chokidar@^3.5.1: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -classnames@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" - integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== - -cliui@7.0.4, cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -clsx@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" - integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colorette@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -css-color-keywords@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" - integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg== - -css-to-react-native@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32" - integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ== - dependencies: - camelize "^1.0.0" - css-color-keywords "^1.0.0" - postcss-value-parser "^4.0.2" - -data-uri-to-buffer@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" - integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== - -data-uri-to-buffer@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz#d296973d5a4897a5dbe31716d118211921f04770" - integrity sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA== - -debug@4, debug@^4.1.0, debug@^4.3.1: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -decko@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decko/-/decko-1.2.0.tgz#fd43c735e967b8013306884a56fbe665996b6817" - integrity sha512-m8FnyHXV1QX+S1cl+KPFDIl6NMkxtKsy6+U/aYyjrOqWMuwAwYWu7ePqrsUHtDR5Y8Yk2pi/KIDSgF+vT4cPOQ== - -deep-is@~0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" - integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -degenerator@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-3.0.3.tgz#a081ac30052ca84e1d1c6e86c972ae8dabbc4079" - integrity sha512-FTq/qYMeBJACu1gHcXJvzsRBTK6aw5zWCYbEnIOyamOt5UJufWJRQ5XfDb6OuayfJWvmWAHgcZyt43vm/hbj7g== - dependencies: - ast-types "^0.13.2" - escodegen "^1.8.1" - esprima "^4.0.0" - vm2 "^3.9.11" - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -dependency-graph@0.11.0, dependency-graph@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" - integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== - -dompurify@^2.2.8: - version "2.4.5" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.5.tgz#0e89a27601f0bad978f9a924e7a05d5d2cccdd87" - integrity sha512-jggCCd+8Iqp4Tsz0nIvpcb22InKEBrGz5dw3EQJMs8HPJDsKbFIO3STYtAvCfDx26Muevn1MHVI0XxjgFfmiSA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -eol@0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" - integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== - -es-abstract@^1.19.0, es-abstract@^1.20.4: - version "1.21.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" - integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== - dependencies: - array-buffer-byte-length "^1.0.0" - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-set-tostringtag "^2.0.1" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.2.0" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.10" - is-weakref "^1.0.2" - object-inspect "^1.12.3" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.7" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.9" - -es-aggregate-error@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/es-aggregate-error/-/es-aggregate-error-1.0.9.tgz#b50925cdf78c8a634bd766704f6f7825902be3d9" - integrity sha512-fvnX40sb538wdU6r4s35cq4EY6Lr09Upj40BEVem4LEsuW8XgQep9yD5Q1U2KftokNp1rWODFJ2qwZSsAjFpbg== - dependencies: - define-properties "^1.1.4" - es-abstract "^1.20.4" - function-bind "^1.1.1" - functions-have-names "^1.2.3" - get-intrinsic "^1.1.3" - globalthis "^1.0.3" - has-property-descriptors "^1.0.0" - -es-set-tostringtag@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" - integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== - dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" - has-tostringtag "^1.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es6-promise@^3.2.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" - integrity sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escodegen@^1.8.1: - version "1.14.3" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" - integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== - dependencies: - esprima "^4.0.1" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -esprima@^4.0.0, esprima@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -estraverse@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estree-walker@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" - integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== - -estree-walker@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - -eventemitter3@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -expected-node-version@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/expected-node-version/-/expected-node-version-1.0.2.tgz#b8d225b9bf676a9e87e06dbd615b52fc9d1e386b" - integrity sha512-OSaCdgF02srujDqJz1JWGpqk8Rq3uNYHLmtpBHJrZN3BvuMvzijJMqRVxZN1qLJtKVwjXhmOp+lfsRUqx8n54w== - -fast-deep-equal@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fast-memoize@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/fast-memoize/-/fast-memoize-2.5.2.tgz#79e3bb6a4ec867ea40ba0e7146816f6cdce9b57e" - integrity sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw== - -fast-safe-stringify@^2.0.7: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - -fastq@^1.6.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" - integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== - dependencies: - reusify "^1.0.4" - -file-uri-to-path@2: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz#7b415aeba227d575851e0a5b0c640d7656403fba" - integrity sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -foreach@^2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.6.tgz#87bcc8a1a0e74000ff2bf9802110708cfb02eb6e" - integrity sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg== - -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -ftp@^0.3.10: - version "0.3.10" - resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d" - integrity sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ== - dependencies: - readable-stream "1.1.x" - xregexp "2.0.0" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functions-have-names@^1.2.2, functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" - integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-source@^2.0.12: - version "2.0.12" - resolved "https://registry.yarnpkg.com/get-source/-/get-source-2.0.12.tgz#0b47d57ea1e53ce0d3a69f4f3d277eb8047da944" - integrity sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w== - dependencies: - data-uri-to-buffer "^2.0.0" - source-map "^0.6.1" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -get-uri@3: - version "3.0.2" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c" - integrity sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg== - dependencies: - "@tootallnate/once" "1" - data-uri-to-buffer "3" - debug "4" - file-uri-to-path "2" - fs-extra "^8.1.0" - ftp "^0.3.10" - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-promise@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/glob-promise/-/glob-promise-3.4.0.tgz#b6b8f084504216f702dc2ce8c9bc9ac8866fdb20" - integrity sha512-q08RJ6O+eJn+dVanerAndJwIcumgbDdYiUT7zFQl3Wm1xD6fBKtah7H8ZJChj4wP+8C+QfeVy8xautR7rdmKEw== - dependencies: - "@types/glob" "*" - -glob@^7.1.6: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globalthis@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" - integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== - dependencies: - define-properties "^1.1.3" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -handlebars@^4.7.6: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.0" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hoist-non-react-statics@^3.0.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" - -http2-client@^1.2.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/http2-client/-/http2-client-1.3.5.tgz#20c9dc909e3cc98284dd20af2432c524086df181" - integrity sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA== - -https-proxy-agent@5, https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -immer@^9.0.6: - version "9.0.21" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" - integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" - integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== - dependencies: - get-intrinsic "^1.2.0" - has "^1.0.3" - side-channel "^1.0.4" - -ip@^1.1.5: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" - integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== - -ip@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" - integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== - -is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" - integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.0" - is-typed-array "^1.1.10" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.12.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4" - integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-reference@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" - integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== - dependencies: - "@types/estree" "*" - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.10, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== - -js-levenshtein@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" - integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsep@^1.1.2, jsep@^1.2.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.3.8.tgz#facb6eb908d085d71d950bd2b24b757c7b8a46d7" - integrity sha512-qofGylTGgYj9gZFsHuyWAN4jr35eJ66qJCK4eKDnldohuUoQFbU3iZn2zjvEbd9wOAhP9Wx5DsAAduTyE1PSWQ== - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-pointer@0.6.2, json-pointer@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/json-pointer/-/json-pointer-0.6.2.tgz#f97bd7550be5e9ea901f8c9264c9d436a22a93cd" - integrity sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw== - dependencies: - foreach "^2.0.4" - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -jsonc-parser@~2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc" - integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w== - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== - optionalDependencies: - graceful-fs "^4.1.6" - -jsonpath-plus@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-7.1.0.tgz#9ac63c3d32a4d91ada68d57e056cb7983e73290a" - integrity sha512-gTaNRsPWO/K2KY6MrqaUFClF9kmuM6MFH5Dhg1VYDODgFbByw1yb7xu3hrViE/sz+dGOeMWgCzwUwQtAnCTE9g== - -jsonpath-plus@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-6.0.1.tgz#9a3e16cedadfab07a3d8dc4e8cd5df4ed8f49c4d" - integrity sha512-EvGovdvau6FyLexFH2OeXfIITlgIbgZoAZe3usiySeaIDm5QS+A10DKNpaPBBqqRSZr2HN6HVNXxtwUAr2apEw== - -jsonpointer@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" - integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== - -lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== - -lodash.set@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" - integrity sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg== - -lodash.topath@^4.5.2: - version "4.5.2" - resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009" - integrity sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg== - -lodash@^4.17.14, lodash@^4.17.21, lodash@~4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lunr@^2.3.9: - version "2.3.9" - resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" - integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== - -magic-string@^0.25.7: - version "0.25.9" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" - integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== - dependencies: - sourcemap-codec "^1.4.8" - -mark.js@^8.11.1: - version "8.11.1" - resolved "https://registry.yarnpkg.com/mark.js/-/mark.js-8.11.1.tgz#180f1f9ebef8b0e638e4166ad52db879beb2ffc5" - integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== - -marked@^4.0.15: - version "4.3.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" - integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== - -merge2@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -minimatch@3.1.2, minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -minimist@^1.2.5, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -mkdirp@^0.5.6: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mobx-react-lite@^3.4.0: - version "3.4.3" - resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.4.3.tgz#3a4c22c30bfaa8b1b2aa48d12b2ba811c0947ab7" - integrity sha512-NkJREyFTSUXR772Qaai51BnE1voWx56LOL80xG7qkZr6vo8vEaLF3sz1JNUVh+rxmUzxYaqOhfuxTfqUh0FXUg== - -mobx-react@^7.2.0: - version "7.6.0" - resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-7.6.0.tgz#ebf0456728a9bd2e5c24fdcf9b36e285a222a7d6" - integrity sha512-+HQUNuh7AoQ9ZnU6c4rvbiVVl+wEkb9WqYsVDzGLng+Dqj1XntHu79PvEWKtSMoMj67vFp/ZPXcElosuJO8ckA== - dependencies: - mobx-react-lite "^3.4.0" - -mobx@^6.3.2: - version "6.9.0" - resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.9.0.tgz#8a894c26417c05bed2cf7499322e589ee9787397" - integrity sha512-HdKewQEREEJgsWnErClfbFoVebze6rGazxFLU/XUyrII8dORfVszN1V0BMRnQSzcgsNNtkX8DHj3nC6cdWE9YQ== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -neo-async@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -netmask@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" - integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== - -nimma@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/nimma/-/nimma-0.2.2.tgz#48d00f837d17b4baa23beec22ac1380f152f15ef" - integrity sha512-V52MLl7BU+tH2Np9tDrIXK8bql3MVUadnMIl/0/oZSGC9keuro0O9UUv9QKp0aMvtN8HRew4G7byY7H4eWsxaQ== - dependencies: - "@jsep-plugin/regex" "^1.0.1" - "@jsep-plugin/ternary" "^1.0.2" - astring "^1.8.1" - jsep "^1.2.0" - optionalDependencies: - jsonpath-plus "^6.0.1" - lodash.topath "^4.5.2" - -node-fetch-h2@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz#c6188325f9bd3d834020bf0f2d6dc17ced2241ac" - integrity sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg== - dependencies: - http2-client "^1.2.5" - -node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: - version "2.6.9" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" - integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== - dependencies: - whatwg-url "^5.0.0" - -node-readfiles@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/node-readfiles/-/node-readfiles-0.2.0.tgz#dbbd4af12134e2e635c245ef93ffcf6f60673a5d" - integrity sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA== - dependencies: - es6-promise "^3.2.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -oas-kit-common@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/oas-kit-common/-/oas-kit-common-1.0.8.tgz#6d8cacf6e9097967a4c7ea8bcbcbd77018e1f535" - integrity sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ== - dependencies: - fast-safe-stringify "^2.0.7" - -oas-linter@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/oas-linter/-/oas-linter-3.2.2.tgz#ab6a33736313490659035ca6802dc4b35d48aa1e" - integrity sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ== - dependencies: - "@exodus/schemasafe" "^1.0.0-rc.2" - should "^13.2.1" - yaml "^1.10.0" - -oas-resolver@^2.5.6: - version "2.5.6" - resolved "https://registry.yarnpkg.com/oas-resolver/-/oas-resolver-2.5.6.tgz#10430569cb7daca56115c915e611ebc5515c561b" - integrity sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ== - dependencies: - node-fetch-h2 "^2.3.0" - oas-kit-common "^1.0.8" - reftools "^1.1.9" - yaml "^1.10.0" - yargs "^17.0.1" - -oas-schema-walker@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz#74c3cd47b70ff8e0b19adada14455b5d3ac38a22" - integrity sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ== - -oas-validator@^5.0.8: - version "5.0.8" - resolved "https://registry.yarnpkg.com/oas-validator/-/oas-validator-5.0.8.tgz#387e90df7cafa2d3ffc83b5fb976052b87e73c28" - integrity sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw== - dependencies: - call-me-maybe "^1.0.1" - oas-kit-common "^1.0.8" - oas-linter "^3.2.2" - oas-resolver "^2.5.6" - oas-schema-walker "^1.1.5" - reftools "^1.1.9" - should "^13.2.1" - yaml "^1.10.0" - -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.12.3, object-inspect@^1.9.0: - version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -openapi-sampler@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/openapi-sampler/-/openapi-sampler-1.3.1.tgz#eebb2a1048f830cc277398bc8022b415f887e859" - integrity sha512-Ert9mvc2tLPmmInwSyGZS+v4Ogu9/YoZuq9oP3EdUklg2cad6+IGndP9yqJJwbgdXwZibiq5fpv6vYujchdJFg== - dependencies: - "@types/json-schema" "^7.0.7" - json-pointer "0.6.2" - -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -pac-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz#b718f76475a6a5415c2efbe256c1c971c84f635e" - integrity sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" - get-uri "3" - http-proxy-agent "^4.0.1" - https-proxy-agent "5" - pac-resolver "^5.0.0" - raw-body "^2.2.0" - socks-proxy-agent "5" - -pac-resolver@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-5.0.1.tgz#c91efa3a9af9f669104fa2f51102839d01cde8e7" - integrity sha512-cy7u00ko2KVgBAjuhevqpPeHIkCIqPe1v24cydhWjmeuzaBfmUWFCZJ1iAh5TuVzVZoUzXIW7K8sMYOZ84uZ9Q== - dependencies: - degenerator "^3.0.2" - ip "^1.1.5" - netmask "^2.0.2" - -path-browserify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -perfect-scrollbar@^1.5.5: - version "1.5.5" - resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz#41a211a2fb52a7191eff301432134ea47052b27f" - integrity sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.0, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pluralize@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" - integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== - -polished@^4.1.3: - version "4.2.2" - resolved "https://registry.yarnpkg.com/polished/-/polished-4.2.2.tgz#2529bb7c3198945373c52e34618c8fe7b1aa84d1" - integrity sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ== - dependencies: - "@babel/runtime" "^7.17.8" - -pony-cause@1.1.1, pony-cause@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pony-cause/-/pony-cause-1.1.1.tgz#f795524f83bebbf1878bd3587b45f69143cbf3f9" - integrity sha512-PxkIc/2ZpLiEzQXu5YRDOUgBlfGYBY8156HY5ZcRAwwonMk5W/MrJP2LLkG/hF7GEQzaHo2aS7ho6ZLCOvf+6g== - -portfinder@^1.0.26: - version "1.0.32" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" - integrity sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg== - dependencies: - async "^2.6.4" - debug "^3.2.7" - mkdirp "^0.5.6" - -postcss-value-parser@^4.0.2: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - -printable-characters@^1.0.42: - version "1.0.42" - resolved "https://registry.yarnpkg.com/printable-characters/-/printable-characters-1.0.42.tgz#3f18e977a9bd8eb37fcc4ff5659d7be90868b3d8" - integrity sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ== - -prismjs@^1.27.0: - version "1.29.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" - integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== - -prop-types@^15.5.0, prop-types@^15.7.2: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -proxy-agent@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-5.0.0.tgz#d31405c10d6e8431fde96cba7a0c027ce01d633b" - integrity sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g== - dependencies: - agent-base "^6.0.0" - debug "4" - http-proxy-agent "^4.0.0" - https-proxy-agent "^5.0.0" - lru-cache "^5.1.1" - pac-proxy-agent "^5.0.0" - proxy-from-env "^1.0.0" - socks-proxy-agent "^5.0.0" - -proxy-from-env@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -punycode@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" - integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -raw-body@^2.2.0: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -react-dom@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" - integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler "^0.20.2" - -react-is@^16.13.1, react-is@^16.7.0: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-tabs@^3.2.2: - version "3.2.3" - resolved "https://registry.yarnpkg.com/react-tabs/-/react-tabs-3.2.3.tgz#ccbb3e1241ad3f601047305c75db661239977f2f" - integrity sha512-jx325RhRVnS9DdFbeF511z0T0WEqEoMl1uCE3LoZ6VaZZm7ytatxbum0B8bCTmaiV0KsU+4TtLGTGevCic7SWg== - dependencies: - clsx "^1.1.0" - prop-types "^15.5.0" - -react@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" - integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -readable-stream@1.1.x: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^3.6.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -redoc@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/redoc/-/redoc-2.0.0.tgz#8b3047ca75b84d31558c6c92da7f84affef35c3e" - integrity sha512-rU8iLdAkT89ywOkYk66Mr+IofqaMASlRvTew0dJvopCORMIPUcPMxjlJbJNC6wsn2vvMnpUFLQ/0ISDWn9BWag== - dependencies: - "@redocly/openapi-core" "^1.0.0-beta.104" - classnames "^2.3.1" - decko "^1.2.0" - dompurify "^2.2.8" - eventemitter3 "^4.0.7" - json-pointer "^0.6.2" - lunr "^2.3.9" - mark.js "^8.11.1" - marked "^4.0.15" - mobx-react "^7.2.0" - openapi-sampler "^1.3.0" - path-browserify "^1.0.1" - perfect-scrollbar "^1.5.5" - polished "^4.1.3" - prismjs "^1.27.0" - prop-types "^15.7.2" - react-tabs "^3.2.2" - slugify "~1.4.7" - stickyfill "^1.1.1" - style-loader "^3.3.1" - swagger2openapi "^7.0.6" - url-template "^2.0.8" - -reftools@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/reftools/-/reftools-1.1.9.tgz#e16e19f662ccd4648605312c06d34e5da3a2b77e" - integrity sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w== - -regenerator-runtime@^0.13.11: - version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== - -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -reserved@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/reserved/-/reserved-0.1.2.tgz#707b1246a3269f755da7cfcf9af6f4983bef105c" - integrity sha512-/qO54MWj5L8WCBP9/UNe2iefJc+L9yETbH32xO/ft/EYPOTCR5k+azvDUgdCOKwZH8hXwPd0b8XBL78Nn2U69g== - -resolve@^1.17.0: - version "1.22.3" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.3.tgz#4b4055349ffb962600972da1fdc33c46a4eb3283" - integrity sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw== - dependencies: - is-core-module "^2.12.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rollup@~2.79.0: - version "2.79.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" - integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== - optionalDependencies: - fsevents "~2.3.2" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - is-regex "^1.1.4" - -safe-stable-stringify@^1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz#c8a220ab525cd94e60ebf47ddc404d610dc5d84a" - integrity sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw== - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -scheduler@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" - integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -semver@^5.0.3: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shallowequal@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" - integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== - -should-equal@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" - integrity sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA== - dependencies: - should-type "^1.4.0" - -should-format@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/should-format/-/should-format-3.0.3.tgz#9bfc8f74fa39205c53d38c34d717303e277124f1" - integrity sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q== - dependencies: - should-type "^1.3.0" - should-type-adaptors "^1.0.1" - -should-type-adaptors@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz#401e7f33b5533033944d5cd8bf2b65027792e27a" - integrity sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA== - dependencies: - should-type "^1.3.0" - should-util "^1.0.0" - -should-type@^1.3.0, should-type@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/should-type/-/should-type-1.4.0.tgz#0756d8ce846dfd09843a6947719dfa0d4cff5cf3" - integrity sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ== - -should-util@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/should-util/-/should-util-1.0.1.tgz#fb0d71338f532a3a149213639e2d32cbea8bcb28" - integrity sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g== - -should@^13.2.1: - version "13.2.3" - resolved "https://registry.yarnpkg.com/should/-/should-13.2.3.tgz#96d8e5acf3e97b49d89b51feaa5ae8d07ef58f10" - integrity sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ== - dependencies: - should-equal "^2.0.0" - should-format "^3.0.3" - should-type "^1.4.0" - should-type-adaptors "^1.0.1" - should-util "^1.0.0" - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -simple-eval@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-eval/-/simple-eval-1.0.0.tgz#7ba8e6049840690b2d4e356ed01f13209e03aad1" - integrity sha512-kpKJR+bqTscgC0xuAl2xHN6bB12lHjC2DCUfqjAx19bQyO3R2EVLOurm3H9AUltv/uFVcSCVNc6faegR+8NYLw== - dependencies: - jsep "^1.1.2" - -simple-websocket@^9.0.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/simple-websocket/-/simple-websocket-9.1.0.tgz#91cbb39eafefbe7e66979da6c639109352786a7f" - integrity sha512-8MJPnjRN6A8UCp1I+H/dSFyjwJhp6wta4hsVRhjf8w9qBHRzxYt14RaOcjvQnhD1N4yKOddEjflwMnQM4VtXjQ== - dependencies: - debug "^4.3.1" - queue-microtask "^1.2.2" - randombytes "^2.1.0" - readable-stream "^3.6.0" - ws "^7.4.2" - -slugify@~1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.7.tgz#e42359d505afd84a44513280868e31202a79a628" - integrity sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg== - -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== - -socks-proxy-agent@5, socks-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz#032fb583048a29ebffec2e6a73fca0761f48177e" - integrity sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ== - dependencies: - agent-base "^6.0.2" - debug "4" - socks "^2.3.3" - -socks@^2.3.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" - integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== - dependencies: - ip "^2.0.0" - smart-buffer "^4.2.0" - -source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sourcemap-codec@^1.4.8: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - -stacktracey@^2.1.7: - version "2.1.8" - resolved "https://registry.yarnpkg.com/stacktracey/-/stacktracey-2.1.8.tgz#bf9916020738ce3700d1323b32bd2c91ea71199d" - integrity sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw== - dependencies: - as-table "^1.0.36" - get-source "^2.0.12" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -stickyfill@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stickyfill/-/stickyfill-1.1.1.tgz#39413fee9d025c74a7e59ceecb23784cc0f17f02" - integrity sha512-GCp7vHAfpao+Qh/3Flh9DXEJ/qSi0KJwJw6zYlZOtRYXWUIpMM6mC2rIep/dK8RQqwW0KxGJIllmjPIBOGN8AA== - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string.prototype.trim@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" - integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -string.prototype.trimend@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" - integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -string.prototype.trimstart@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" - integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== - -strip-ansi@6.0, strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -style-loader@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.2.tgz#eaebca714d9e462c19aa1e3599057bc363924899" - integrity sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw== - -styled-components@5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.3.tgz#312a3d9a549f4708f0fb0edc829eb34bde032743" - integrity sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/traverse" "^7.4.5" - "@emotion/is-prop-valid" "^0.8.8" - "@emotion/stylis" "^0.8.4" - "@emotion/unitless" "^0.7.4" - babel-plugin-styled-components ">= 1.12.0" - css-to-react-native "^3.0.0" - hoist-non-react-statics "^3.0.0" - shallowequal "^1.1.0" - supports-color "^5.5.0" - -supports-color@^5.3.0, supports-color@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -swagger2openapi@^7.0.6: - version "7.0.8" - resolved "https://registry.yarnpkg.com/swagger2openapi/-/swagger2openapi-7.0.8.tgz#12c88d5de776cb1cbba758994930f40ad0afac59" - integrity sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g== - dependencies: - call-me-maybe "^1.0.1" - node-fetch "^2.6.1" - node-fetch-h2 "^2.3.0" - node-readfiles "^0.2.0" - oas-kit-common "^1.0.8" - oas-resolver "^2.5.6" - oas-schema-walker "^1.1.5" - oas-validator "^5.0.8" - reftools "^1.1.9" - yaml "^1.10.0" - yargs "^17.0.1" - -text-table@0.2: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -tslib@^1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.0.1, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" - integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - -typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== - dependencies: - call-bind "^1.0.2" - for-each "^0.3.3" - is-typed-array "^1.1.9" - -uglify-js@^3.1.4: - version "3.17.4" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" - integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -unpipe@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -urijs@^1.19.11: - version "1.19.11" - resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" - integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== - -url-template@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" - integrity sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw== - -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -utility-types@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" - integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== - -validate-npm-package-name@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" - integrity sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw== - dependencies: - builtins "^1.0.3" - -vm2@^3.9.11: - version "3.9.17" - resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.17.tgz#251b165ff8a0e034942b5181057305e39570aeab" - integrity sha512-AqwtCnZ/ERcX+AVj9vUsphY56YANXxRuqMb7GsDtAr0m0PcQX3u0Aj3KWiXM0YAHy7i6JEeHrwOnwXbGYgRpAw== - dependencies: - acorn "^8.7.0" - acorn-walk "^8.2.0" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" - -word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -ws@^7.4.2: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== - -xregexp@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" - integrity sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yaml-ast-parser@0.0.43: - version "0.0.43" - resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" - integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A== - -yaml@^1.10.0: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-parser@^21.0.0, yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@17.0.1: - version "17.0.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.0.1.tgz#6a1ced4ed5ee0b388010ba9fd67af83b9362e0bb" - integrity sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - -yargs@17.3.1: - version "17.3.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" - integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.0.0" - -yargs@^17.0.1: - version "17.7.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" - integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" diff --git a/spec/BUILD.bazel b/spec/BUILD.bazel index 88f9cea64..cc46f413c 100644 --- a/spec/BUILD.bazel +++ b/spec/BUILD.bazel @@ -1,104 +1,91 @@ -load("@com_github_scionproto_scion//rules_openapi:defs.bzl", "openapi_bundle") load("//tools/lint:write_source_files.bzl", "write_source_files") +load("//private/mgmtapi:api.bzl", "openapi_bundle") openapi_bundle( name = "control", srcs = [ - "//spec/common:base.yml", - "//spec/common:process.yml", - "//spec/control:beacons.yml", - "//spec/control:cppki.yml", - "//spec/cppki:spec.yml", - "//spec/health:spec.yml", - "//spec/segments:spec.yml", + "//spec/common:files", + "//spec/control:files", + "//spec/cppki:spec", + "//spec/health:spec", + "//spec/segments:spec", ], - entrypoint = "//spec/control:spec.yml", + entrypoint = "//spec/control:spec", visibility = ["//visibility:public"], ) openapi_bundle( name = "ca", srcs = [ - "//spec/ca:auth.yml", - "//spec/ca:health.yml", - "//spec/ca:problem.yml", - "//spec/ca:ra.yml", + "//spec/ca:files", ], - entrypoint = "//spec/ca:spec.yml", + entrypoint = "//spec/ca:spec", visibility = ["//visibility:public"], ) openapi_bundle( name = "dispatcher", srcs = [ - "//spec/common:base.yml", - "//spec/common:process.yml", + "//spec/common:files", ], - entrypoint = "//spec/dispatcher:spec.yml", + entrypoint = "//spec/dispatcher:spec", visibility = ["//visibility:public"], ) openapi_bundle( name = "daemon", srcs = [ - "//spec/common:base.yml", - "//spec/common:process.yml", - "//spec/cppki:spec.yml", - "//spec/segments:spec.yml", + "//spec/common:files", + "//spec/cppki:spec", + "//spec/segments:spec", ], - entrypoint = "//spec/daemon:spec.yml", + entrypoint = "//spec/daemon:spec", visibility = ["//visibility:public"], ) openapi_bundle( name = "gateway", srcs = [ - "//spec/common:base.yml", - "//spec/common:process.yml", + "//spec/common:files", ], - entrypoint = "//spec/gateway:spec.yml", + entrypoint = "//spec/gateway:spec", visibility = ["//visibility:public"], ) openapi_bundle( name = "router", srcs = [ - "//spec/common:base.yml", - "//spec/common:process.yml", - "//spec/common:scion.yml", - "//spec/router:interfaces.yml", + "//spec/common:files", + "//spec/router:files", ], - entrypoint = "//spec/router:spec.yml", + entrypoint = "//spec/router:spec", visibility = ["//visibility:public"], ) openapi_bundle( name = "segments", srcs = [ - "//spec/common:base.yml", - "//spec/common:process.yml", + "//spec/common:files", ], - entrypoint = "//spec/segments:spec.yml", + entrypoint = "//spec/segments:spec", visibility = ["//visibility:public"], ) openapi_bundle( name = "cppki", srcs = [ - "//spec/common:base.yml", - "//spec/common:process.yml", + "//spec/common:files", ], - entrypoint = "//spec/cppki:spec.yml", + entrypoint = "//spec/cppki:spec", visibility = ["//visibility:public"], ) openapi_bundle( name = "health", srcs = [ - "//spec/common:base.yml", - "//spec/common:process.yml", + "//spec/common:files", ], - entrypoint = "//spec/health:spec.yml", + entrypoint = "//spec/health:spec", visibility = ["//visibility:public"], ) diff --git a/spec/ca/BUILD.bazel b/spec/ca/BUILD.bazel index d721cc8ca..91a11d0d5 100644 --- a/spec/ca/BUILD.bazel +++ b/spec/ca/BUILD.bazel @@ -1 +1,16 @@ -exports_files(glob(["*.yml"])) +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") + +copy_to_bin( + name = "spec", + srcs = ["spec.yml"], + visibility = ["//spec:__subpackages__"], +) + +copy_to_bin( + name = "files", + srcs = glob( + ["*.yml"], + exclude = ["spec.yml"], + ), + visibility = ["//spec:__subpackages__"], +) diff --git a/spec/common/BUILD.bazel b/spec/common/BUILD.bazel index d721cc8ca..d120912d7 100644 --- a/spec/common/BUILD.bazel +++ b/spec/common/BUILD.bazel @@ -1 +1,7 @@ -exports_files(glob(["*.yml"])) +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") + +copy_to_bin( + name = "files", + srcs = glob(["*.yml"]), + visibility = ["//spec:__subpackages__"], +) diff --git a/spec/control/BUILD.bazel b/spec/control/BUILD.bazel index d721cc8ca..5fed18363 100644 --- a/spec/control/BUILD.bazel +++ b/spec/control/BUILD.bazel @@ -1 +1,16 @@ -exports_files(glob(["*.yml"])) +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") + +copy_to_bin( + name = "spec", + srcs = ["spec.yml"], + visibility = ["//spec:__subpackages__"], +) + +copy_to_bin( + name = "files", + srcs = [ + "beacons.yml", + "cppki.yml", + ], + visibility = ["//spec:__subpackages__"], +) diff --git a/spec/cppki/BUILD.bazel b/spec/cppki/BUILD.bazel index d721cc8ca..df1bb2a71 100644 --- a/spec/cppki/BUILD.bazel +++ b/spec/cppki/BUILD.bazel @@ -1 +1,7 @@ -exports_files(glob(["*.yml"])) +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") + +copy_to_bin( + name = "spec", + srcs = ["spec.yml"], + visibility = ["//spec:__subpackages__"], +) diff --git a/spec/daemon/BUILD.bazel b/spec/daemon/BUILD.bazel index d721cc8ca..df1bb2a71 100644 --- a/spec/daemon/BUILD.bazel +++ b/spec/daemon/BUILD.bazel @@ -1 +1,7 @@ -exports_files(glob(["*.yml"])) +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") + +copy_to_bin( + name = "spec", + srcs = ["spec.yml"], + visibility = ["//spec:__subpackages__"], +) diff --git a/spec/dispatcher/BUILD.bazel b/spec/dispatcher/BUILD.bazel index d721cc8ca..df1bb2a71 100644 --- a/spec/dispatcher/BUILD.bazel +++ b/spec/dispatcher/BUILD.bazel @@ -1 +1,7 @@ -exports_files(glob(["*.yml"])) +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") + +copy_to_bin( + name = "spec", + srcs = ["spec.yml"], + visibility = ["//spec:__subpackages__"], +) diff --git a/spec/gateway/BUILD.bazel b/spec/gateway/BUILD.bazel index d721cc8ca..df1bb2a71 100644 --- a/spec/gateway/BUILD.bazel +++ b/spec/gateway/BUILD.bazel @@ -1 +1,7 @@ -exports_files(glob(["*.yml"])) +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") + +copy_to_bin( + name = "spec", + srcs = ["spec.yml"], + visibility = ["//spec:__subpackages__"], +) diff --git a/spec/health/BUILD.bazel b/spec/health/BUILD.bazel index d721cc8ca..df1bb2a71 100644 --- a/spec/health/BUILD.bazel +++ b/spec/health/BUILD.bazel @@ -1 +1,7 @@ -exports_files(glob(["*.yml"])) +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") + +copy_to_bin( + name = "spec", + srcs = ["spec.yml"], + visibility = ["//spec:__subpackages__"], +) diff --git a/spec/router/BUILD.bazel b/spec/router/BUILD.bazel index d721cc8ca..91a11d0d5 100644 --- a/spec/router/BUILD.bazel +++ b/spec/router/BUILD.bazel @@ -1 +1,16 @@ -exports_files(glob(["*.yml"])) +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") + +copy_to_bin( + name = "spec", + srcs = ["spec.yml"], + visibility = ["//spec:__subpackages__"], +) + +copy_to_bin( + name = "files", + srcs = glob( + ["*.yml"], + exclude = ["spec.yml"], + ), + visibility = ["//spec:__subpackages__"], +) diff --git a/spec/segments/BUILD.bazel b/spec/segments/BUILD.bazel index d721cc8ca..df1bb2a71 100644 --- a/spec/segments/BUILD.bazel +++ b/spec/segments/BUILD.bazel @@ -1 +1,7 @@ -exports_files(glob(["*.yml"])) +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") + +copy_to_bin( + name = "spec", + srcs = ["spec.yml"], + visibility = ["//spec:__subpackages__"], +) diff --git a/tools/licenses.sh b/tools/licenses.sh index efe032d14..fd96b4629 100755 --- a/tools/licenses.sh +++ b/tools/licenses.sh @@ -14,7 +14,7 @@ rm -rf $DSTDIR (cd $EXECROOT/external; find -L . -iregex '.*\(LICENSE\|COPYING\).*') | while IFS= read -r path ; do # skip over node JS stuff, this is only used during build time. - if [[ "$path" =~ "node_modules" || "$path" =~ "nodejs" ]]; then + if [[ "$path" =~ "node_modules" || "$path" =~ "nodejs" || "$path" =~ "rules_license" ]]; then continue fi dst=$DSTDIR/$(dirname $path) @@ -35,3 +35,7 @@ rm -rf $DSTDIR/org_uber_go_zap/checklicense.sh rm -rf $DSTDIR/org_golang_x_tools/gopls/ rm -rf $DSTDIR/org_golang_x_tools/internal/lsp/cmd/usage/licenses.hlp rm -rf $DSTDIR/com_github_google_certificate_transparency_go/scripts +rm -rf $DSTDIR/python3_10_x86_64-unknown-linux-gnu/ +rm -rf $DSTDIR/aspect_bazel_lib/ +rm -rf $DSTDIR/aspect_rules_js/ +rm -rf $DSTDIR/npm__*/ diff --git a/tools/lint/go.bzl b/tools/lint/go.bzl index a70246f2f..42662ad98 100644 --- a/tools/lint/go.bzl +++ b/tools/lint/go.bzl @@ -2,7 +2,6 @@ load("@apple_rules_lint//lint:defs.bzl", "get_lint_config") load("@io_bazel_rules_go//go:def.bzl", _go_library = "go_library", _go_test = "go_test") load(":impi.bzl", "impi_test") load(":ineffassign.bzl", "ineffassign_test") -load(":go_embed.bzl", _go_embed_data = "go_embed_data") def _add_go_lint_tests(name, **kwargs): tags = kwargs.get("tags", []) @@ -37,5 +36,3 @@ def go_test(name, **kwargs): tags = tags + ["unit"] kwargs["tags"] = tags _go_test(name = name, **kwargs) - -go_embed_data = _go_embed_data diff --git a/tools/lint/go_embed.bzl b/tools/lint/go_embed.bzl deleted file mode 100644 index 9e47b4ebb..000000000 --- a/tools/lint/go_embed.bzl +++ /dev/null @@ -1,23 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", _go_embed_data = "go_embed_data") -load(":go_fmt.bzl", _go_fmt = "go_fmt") - -def go_embed_data( - name, - srcs, - flatten, - var, - out_src = "embedded.gen.go", - *kwargs): - _go_embed_data( - name = name, - srcs = srcs, - flatten = flatten, - var = var, - *kwargs - ) - - fmt_name = name + "-fmt" - _go_fmt( - name = fmt_name, - src = ":" + name, - ) From 8b498a4eef145a57bf48caf15d401fde650ce8e2 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Wed, 1 Nov 2023 22:20:04 +0100 Subject: [PATCH 078/255] build: update quic-go to v0.40.0 (#4431) --- go.mod | 7 ++++--- go.sum | 14 ++++++++------ go_deps.bzl | 18 ++++++++++++------ 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 759cd9b13..67f8b840f 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/procfs v0.12.0 - github.com/quic-go/quic-go v0.38.1 + github.com/quic-go/quic-go v0.40.0 github.com/sergi/go-diff v1.3.1 github.com/smartystreets/goconvey v1.7.2 github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 @@ -98,7 +98,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect - github.com/quic-go/qtls-go1-20 v0.3.3 // indirect + github.com/quic-go/qtls-go1-20 v0.4.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/smartystreets/assertions v1.2.0 // indirect @@ -109,9 +109,10 @@ require ( github.com/uber/jaeger-lib v2.0.0+incompatible // indirect github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect go.uber.org/atomic v1.9.0 // indirect + go.uber.org/mock v0.3.0 // indirect go.uber.org/multierr v1.8.0 // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect - golang.org/x/mod v0.10.0 // indirect + golang.org/x/mod v0.11.0 // indirect golang.org/x/sys v0.12.0 // indirect golang.org/x/text v0.9.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 // indirect diff --git a/go.sum b/go.sum index 8fcf193fa..8efbd3866 100644 --- a/go.sum +++ b/go.sum @@ -362,10 +362,10 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM= -github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE= -github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= +github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= +github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= +github.com/quic-go/quic-go v0.40.0 h1:GYd1iznlKm7dpHD7pOVpUvItgMPo/jrMgDWZhMCecqw= +github.com/quic-go/quic-go v0.40.0/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -445,6 +445,8 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= +go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= @@ -500,8 +502,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/go_deps.bzl b/go_deps.bzl index 1d7c033a6..f1030d3e3 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -1024,14 +1024,14 @@ def go_deps(): go_repository( name = "com_github_quic_go_qtls_go1_20", importpath = "github.com/quic-go/qtls-go1-20", - sum = "h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=", - version = "v0.3.3", + sum = "h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=", + version = "v0.4.1", ) go_repository( name = "com_github_quic_go_quic_go", importpath = "github.com/quic-go/quic-go", - sum = "h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=", - version = "v0.38.1", + sum = "h1:GYd1iznlKm7dpHD7pOVpUvItgMPo/jrMgDWZhMCecqw=", + version = "v0.40.0", ) go_repository( name = "com_github_ravenox_go_jsoncommentstrip", @@ -1464,8 +1464,8 @@ def go_deps(): go_repository( name = "org_golang_x_mod", importpath = "golang.org/x/mod", - sum = "h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=", - version = "v0.10.0", + sum = "h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=", + version = "v0.11.0", ) go_repository( name = "org_golang_x_net", @@ -1611,6 +1611,12 @@ def go_deps(): sum = "h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=", version = "v1.2.1", ) + go_repository( + name = "org_uber_go_mock", + importpath = "go.uber.org/mock", + sum = "h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=", + version = "v0.3.0", + ) go_repository( name = "org_uber_go_multierr", importpath = "go.uber.org/multierr", From a0a89d4b109a2132516cfc2cfa70f8d6ea519346 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Thu, 2 Nov 2023 10:45:51 +0100 Subject: [PATCH 079/255] router: fix interface label of router metrics (#4430) The interface label value of every metric instance had been lost to a refactoring in #4422. --- router/metrics.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/metrics.go b/router/metrics.go index df7af4c74..6c7f9ad7d 100644 --- a/router/metrics.go +++ b/router/metrics.go @@ -283,7 +283,7 @@ func newInterfaceMetrics( localIA addr.IA, neighbors map[uint16]addr.IA) interfaceMetrics { - ifLabels := interfaceLabels(0, localIA, neighbors) + ifLabels := interfaceLabels(id, localIA, neighbors) m := interfaceMetrics{} for sc := minSizeClass; sc < maxSizeClass; sc++ { scLabels := prometheus.Labels{"sizeclass": sc.String()} From 5d697c079858050d7cb6dee220e33f1fa4bdacf2 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Fri, 3 Nov 2023 09:12:00 +0100 Subject: [PATCH 080/255] deps: update oapi-codegen to v2 (#4432) The oapi-codegen libraries went through a reorganization; the repositories for the oapi-codegen build tool was separated from the runtime libraries. In our normal code dependencies, the oapi-codegen build tool no longer shows up. Import it in a dummy .go file as an easy way to ensure that we have all the appropriate dependencies (via the `go.mod`/`go_deps.bzl`) . This leaves some clutter in the `go.mod` file which is not aesthetically pleasing, but is not a real issue due to dependency graph pruning. The alternative solution would have been to manage the dependencies of the `rules_openapi` bazel rules explicitly in a `rules_openapi_dependencies` macro. This turns out to be rather cumbersome, and can lead to unexpected or even invalid dependency version combinations, because `rules_go` does not have a way to separate the dependencies of the build tools from the dependencies of the code. Aside; fix `cfg = "exec"` for the oapi-codegen buildtool so that this tool is built for the environment of the builder, not the target platform. --- control/mgmtapi/BUILD.bazel | 3 +- control/mgmtapi/client.gen.go | 506 +++++++++--------- control/mgmtapi/server.gen.go | 224 ++++++-- control/mgmtapi/spec.gen.go | 12 +- daemon/mgmtapi/BUILD.bazel | 2 +- daemon/mgmtapi/client.gen.go | 288 +++++----- daemon/mgmtapi/server.gen.go | 144 +++-- daemon/mgmtapi/spec.gen.go | 12 +- dispatcher/mgmtapi/client.gen.go | 26 +- dispatcher/mgmtapi/server.gen.go | 52 +- dispatcher/mgmtapi/spec.gen.go | 12 +- gateway/mgmtapi/BUILD.bazel | 2 +- gateway/mgmtapi/client.gen.go | 26 +- gateway/mgmtapi/server.gen.go | 52 +- gateway/mgmtapi/spec.gen.go | 12 +- go.mod | 25 +- go.sum | 55 +- go_deps.bzl | 316 ++++++++--- .../LICENSE | 0 .../data/com_github_labstack_echo_v4/LICENSE | 21 - .../data/com_github_labstack_gommon/LICENSE | 22 - .../com_github_oapi_codegen_runtime/LICENSE | 201 +++++++ .../com_github_valyala_bytebufferpool/LICENSE | 22 - .../com_github_valyala_fasttemplate/LICENSE | 22 - nogo.json | 7 +- private/ca/api/BUILD.bazel | 4 +- private/ca/api/client.gen.go | 96 ++-- private/ca/api/types.gen.go | 28 +- private/mgmtapi/cppki/api/BUILD.bazel | 2 +- private/mgmtapi/cppki/api/client.gen.go | 178 +++--- private/mgmtapi/cppki/api/server.gen.go | 74 ++- private/mgmtapi/health/api/client.gen.go | 6 +- private/mgmtapi/health/api/server.gen.go | 22 +- private/mgmtapi/segments/api/BUILD.bazel | 2 +- private/mgmtapi/segments/api/client.gen.go | 86 +-- private/mgmtapi/segments/api/server.gen.go | 44 +- router/mgmtapi/BUILD.bazel | 3 +- router/mgmtapi/client.gen.go | 38 +- router/mgmtapi/server.gen.go | 62 ++- router/mgmtapi/spec.gen.go | 12 +- rules_openapi/internal/generate.bzl | 4 +- rules_openapi/internal/tools.go | 24 + 42 files changed, 1741 insertions(+), 1008 deletions(-) rename licenses/data/{com_github_deepmap_oapi_codegen => com_github_deepmap_oapi_codegen_v2}/LICENSE (100%) delete mode 100644 licenses/data/com_github_labstack_echo_v4/LICENSE delete mode 100644 licenses/data/com_github_labstack_gommon/LICENSE create mode 100644 licenses/data/com_github_oapi_codegen_runtime/LICENSE delete mode 100644 licenses/data/com_github_valyala_bytebufferpool/LICENSE delete mode 100644 licenses/data/com_github_valyala_fasttemplate/LICENSE create mode 100644 rules_openapi/internal/tools.go diff --git a/control/mgmtapi/BUILD.bazel b/control/mgmtapi/BUILD.bazel index 20d657d1e..71202371e 100644 --- a/control/mgmtapi/BUILD.bazel +++ b/control/mgmtapi/BUILD.bazel @@ -42,10 +42,9 @@ go_library( "//private/mgmtapi/segments/api:go_default_library", "//private/storage:go_default_library", "//private/storage/beacon:go_default_library", - "@com_github_deepmap_oapi_codegen//pkg/runtime:go_default_library", # keep "@com_github_getkin_kin_openapi//openapi3:go_default_library", # keep "@com_github_go_chi_chi_v5//:go_default_library", # keep - "@com_github_pkg_errors//:go_default_library", # keep + "@com_github_oapi_codegen_runtime//:go_default_library", # keep "@org_golang_google_protobuf//proto:go_default_library", ], ) diff --git a/control/mgmtapi/client.gen.go b/control/mgmtapi/client.gen.go index bcc8495fa..c024fae2f 100644 --- a/control/mgmtapi/client.gen.go +++ b/control/mgmtapi/client.gen.go @@ -13,7 +13,7 @@ import ( "net/url" "strings" - "github.com/deepmap/oapi-codegen/pkg/runtime" + "github.com/oapi-codegen/runtime" ) // RequestEditorFn is the function signature for the RequestEditor callback function @@ -122,7 +122,7 @@ type ClientInterface interface { // GetLogLevel request GetLogLevel(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - // SetLogLevel request with any body + // SetLogLevelWithBody request with any body SetLogLevelWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) SetLogLevel(ctx context.Context, body SetLogLevelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -438,122 +438,124 @@ func NewGetBeaconsRequest(server string, params *GetBeaconsParams) (*http.Reques return nil, err } - queryValues := queryURL.Query() + if params != nil { + queryValues := queryURL.Query() - if params.StartIsdAs != nil { + if params.StartIsdAs != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "start_isd_as", runtime.ParamLocationQuery, *params.StartIsdAs); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "start_isd_as", runtime.ParamLocationQuery, *params.StartIsdAs); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - - } - if params.Usages != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "usages", runtime.ParamLocationQuery, *params.Usages); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.Usages != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "usages", runtime.ParamLocationQuery, *params.Usages); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - - } - if params.IngressInterface != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "ingress_interface", runtime.ParamLocationQuery, *params.IngressInterface); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.IngressInterface != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "ingress_interface", runtime.ParamLocationQuery, *params.IngressInterface); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - } - - if params.ValidAt != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "valid_at", runtime.ParamLocationQuery, *params.ValidAt); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.ValidAt != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "valid_at", runtime.ParamLocationQuery, *params.ValidAt); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - - } - if params.All != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.All != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - - } - if params.Desc != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "desc", runtime.ParamLocationQuery, *params.Desc); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.Desc != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "desc", runtime.ParamLocationQuery, *params.Desc); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - } - - if params.Sort != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "sort", runtime.ParamLocationQuery, *params.Sort); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.Sort != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "sort", runtime.ParamLocationQuery, *params.Sort); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } + } + queryURL.RawQuery = queryValues.Encode() } - queryURL.RawQuery = queryValues.Encode() - req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -676,58 +678,60 @@ func NewGetCertificatesRequest(server string, params *GetCertificatesParams) (*h return nil, err } - queryValues := queryURL.Query() + if params != nil { + queryValues := queryURL.Query() - if params.IsdAs != nil { + if params.IsdAs != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "isd_as", runtime.ParamLocationQuery, *params.IsdAs); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "isd_as", runtime.ParamLocationQuery, *params.IsdAs); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - } - - if params.ValidAt != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "valid_at", runtime.ParamLocationQuery, *params.ValidAt); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.ValidAt != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "valid_at", runtime.ParamLocationQuery, *params.ValidAt); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - - } - if params.All != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.All != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } + } + queryURL.RawQuery = queryValues.Encode() } - queryURL.RawQuery = queryValues.Encode() - req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -971,42 +975,44 @@ func NewGetSegmentsRequest(server string, params *GetSegmentsParams) (*http.Requ return nil, err } - queryValues := queryURL.Query() + if params != nil { + queryValues := queryURL.Query() - if params.StartIsdAs != nil { + if params.StartIsdAs != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "start_isd_as", runtime.ParamLocationQuery, *params.StartIsdAs); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "start_isd_as", runtime.ParamLocationQuery, *params.StartIsdAs); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - - } - if params.EndIsdAs != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "end_isd_as", runtime.ParamLocationQuery, *params.EndIsdAs); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.EndIsdAs != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "end_isd_as", runtime.ParamLocationQuery, *params.EndIsdAs); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } + } + queryURL.RawQuery = queryValues.Encode() } - queryURL.RawQuery = queryValues.Encode() - req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -1183,42 +1189,44 @@ func NewGetTrcsRequest(server string, params *GetTrcsParams) (*http.Request, err return nil, err } - queryValues := queryURL.Query() + if params != nil { + queryValues := queryURL.Query() - if params.Isd != nil { + if params.Isd != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "isd", runtime.ParamLocationQuery, *params.Isd); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "isd", runtime.ParamLocationQuery, *params.Isd); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - } - - if params.All != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.All != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } + } + queryURL.RawQuery = queryValues.Encode() } - queryURL.RawQuery = queryValues.Encode() - req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -1366,69 +1374,69 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // GetBeacons request + // GetBeaconsWithResponse request GetBeaconsWithResponse(ctx context.Context, params *GetBeaconsParams, reqEditors ...RequestEditorFn) (*GetBeaconsResponse, error) - // GetBeacon request + // GetBeaconWithResponse request GetBeaconWithResponse(ctx context.Context, segmentId SegmentID, reqEditors ...RequestEditorFn) (*GetBeaconResponse, error) - // GetBeaconBlob request + // GetBeaconBlobWithResponse request GetBeaconBlobWithResponse(ctx context.Context, segmentId SegmentID, reqEditors ...RequestEditorFn) (*GetBeaconBlobResponse, error) - // GetCa request + // GetCaWithResponse request GetCaWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetCaResponse, error) - // GetCertificates request + // GetCertificatesWithResponse request GetCertificatesWithResponse(ctx context.Context, params *GetCertificatesParams, reqEditors ...RequestEditorFn) (*GetCertificatesResponse, error) - // GetCertificate request + // GetCertificateWithResponse request GetCertificateWithResponse(ctx context.Context, chainId ChainID, reqEditors ...RequestEditorFn) (*GetCertificateResponse, error) - // GetCertificateBlob request + // GetCertificateBlobWithResponse request GetCertificateBlobWithResponse(ctx context.Context, chainId ChainID, reqEditors ...RequestEditorFn) (*GetCertificateBlobResponse, error) - // GetConfig request + // GetConfigWithResponse request GetConfigWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetConfigResponse, error) - // GetHealth request + // GetHealthWithResponse request GetHealthWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetHealthResponse, error) - // GetInfo request + // GetInfoWithResponse request GetInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetInfoResponse, error) - // GetLogLevel request + // GetLogLevelWithResponse request GetLogLevelWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetLogLevelResponse, error) - // SetLogLevel request with any body + // SetLogLevelWithBodyWithResponse request with any body SetLogLevelWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetLogLevelResponse, error) SetLogLevelWithResponse(ctx context.Context, body SetLogLevelJSONRequestBody, reqEditors ...RequestEditorFn) (*SetLogLevelResponse, error) - // GetSegments request + // GetSegmentsWithResponse request GetSegmentsWithResponse(ctx context.Context, params *GetSegmentsParams, reqEditors ...RequestEditorFn) (*GetSegmentsResponse, error) - // GetSegment request + // GetSegmentWithResponse request GetSegmentWithResponse(ctx context.Context, segmentId SegmentID, reqEditors ...RequestEditorFn) (*GetSegmentResponse, error) - // GetSegmentBlob request + // GetSegmentBlobWithResponse request GetSegmentBlobWithResponse(ctx context.Context, segmentId SegmentID, reqEditors ...RequestEditorFn) (*GetSegmentBlobResponse, error) - // GetSigner request + // GetSignerWithResponse request GetSignerWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetSignerResponse, error) - // GetSignerChain request + // GetSignerChainWithResponse request GetSignerChainWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetSignerChainResponse, error) - // GetTopology request + // GetTopologyWithResponse request GetTopologyWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetTopologyResponse, error) - // GetTrcs request + // GetTrcsWithResponse request GetTrcsWithResponse(ctx context.Context, params *GetTrcsParams, reqEditors ...RequestEditorFn) (*GetTrcsResponse, error) - // GetTrc request + // GetTrcWithResponse request GetTrcWithResponse(ctx context.Context, isd int, base int, serial int, reqEditors ...RequestEditorFn) (*GetTrcResponse, error) - // GetTrcBlob request + // GetTrcBlobWithResponse request GetTrcBlobWithResponse(ctx context.Context, isd int, base int, serial int, reqEditors ...RequestEditorFn) (*GetTrcBlobResponse, error) } @@ -1438,7 +1446,7 @@ type GetBeaconsResponse struct { JSON200 *struct { Beacons *[]Beacon `json:"beacons,omitempty"` } - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1461,7 +1469,7 @@ type GetBeaconResponse struct { Body []byte HTTPResponse *http.Response JSON200 *BeaconGetResponseJson - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1483,7 +1491,7 @@ func (r GetBeaconResponse) StatusCode() int { type GetBeaconBlobResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1506,7 +1514,7 @@ type GetCaResponse struct { Body []byte HTTPResponse *http.Response JSON200 *CA - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1526,10 +1534,10 @@ func (r GetCaResponse) StatusCode() int { } type GetCertificatesResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *[]ChainBrief - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *[]ChainBrief + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -1549,10 +1557,10 @@ func (r GetCertificatesResponse) StatusCode() int { } type GetCertificateResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *Chain - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *Chain + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -1572,9 +1580,9 @@ func (r GetCertificateResponse) StatusCode() int { } type GetCertificateBlobResponse struct { - Body []byte - HTTPResponse *http.Response - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -1596,7 +1604,7 @@ func (r GetCertificateBlobResponse) StatusCode() int { type GetConfigResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1619,7 +1627,7 @@ type GetHealthResponse struct { Body []byte HTTPResponse *http.Response JSON200 *HealthResponse - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1641,7 +1649,7 @@ func (r GetHealthResponse) StatusCode() int { type GetInfoResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1664,7 +1672,7 @@ type GetLogLevelResponse struct { Body []byte HTTPResponse *http.Response JSON200 *LogLevel - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1687,7 +1695,7 @@ type SetLogLevelResponse struct { Body []byte HTTPResponse *http.Response JSON200 *LogLevel - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1707,10 +1715,10 @@ func (r SetLogLevelResponse) StatusCode() int { } type GetSegmentsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *[]SegmentBrief - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *[]SegmentBrief + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -1730,10 +1738,10 @@ func (r GetSegmentsResponse) StatusCode() int { } type GetSegmentResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *Segment - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *Segment + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -1753,9 +1761,9 @@ func (r GetSegmentResponse) StatusCode() int { } type GetSegmentBlobResponse struct { - Body []byte - HTTPResponse *http.Response - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -1778,7 +1786,7 @@ type GetSignerResponse struct { Body []byte HTTPResponse *http.Response JSON200 *Signer - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1800,7 +1808,7 @@ func (r GetSignerResponse) StatusCode() int { type GetSignerChainResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1823,7 +1831,7 @@ type GetTopologyResponse struct { Body []byte HTTPResponse *http.Response JSON200 *Topology - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1846,7 +1854,7 @@ type GetTrcsResponse struct { Body []byte HTTPResponse *http.Response JSON200 *[]TRCBrief - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1869,7 +1877,7 @@ type GetTrcResponse struct { Body []byte HTTPResponse *http.Response JSON200 *TRC - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1891,7 +1899,7 @@ func (r GetTrcResponse) StatusCode() int { type GetTrcBlobResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -2131,7 +2139,7 @@ func ParseGetBeaconsResponse(rsp *http.Response) (*GetBeaconsResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2164,7 +2172,7 @@ func ParseGetBeaconResponse(rsp *http.Response) (*GetBeaconResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2190,7 +2198,7 @@ func ParseGetBeaconBlobResponse(rsp *http.Response) (*GetBeaconBlobResponse, err switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2223,7 +2231,7 @@ func ParseGetCaResponse(rsp *http.Response) (*GetCaResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2260,7 +2268,7 @@ func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -2293,7 +2301,7 @@ func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, e if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -2319,7 +2327,7 @@ func ParseGetCertificateBlobResponse(rsp *http.Response) (*GetCertificateBlobRes if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -2341,7 +2349,7 @@ func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2374,7 +2382,7 @@ func ParseGetHealthResponse(rsp *http.Response) (*GetHealthResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2400,7 +2408,7 @@ func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2433,7 +2441,7 @@ func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2466,7 +2474,7 @@ func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2503,7 +2511,7 @@ func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -2536,7 +2544,7 @@ func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -2562,7 +2570,7 @@ func ParseGetSegmentBlobResponse(rsp *http.Response) (*GetSegmentBlobResponse, e if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -2591,7 +2599,7 @@ func ParseGetSignerResponse(rsp *http.Response) (*GetSignerResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2617,7 +2625,7 @@ func ParseGetSignerChainResponse(rsp *http.Response) (*GetSignerChainResponse, e switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2650,7 +2658,7 @@ func ParseGetTopologyResponse(rsp *http.Response) (*GetTopologyResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2683,7 +2691,7 @@ func ParseGetTrcsResponse(rsp *http.Response) (*GetTrcsResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2716,7 +2724,7 @@ func ParseGetTrcResponse(rsp *http.Response) (*GetTrcResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2742,7 +2750,7 @@ func ParseGetTrcBlobResponse(rsp *http.Response) (*GetTrcBlobResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/control/mgmtapi/server.gen.go b/control/mgmtapi/server.gen.go index d30513ea9..1419a33f3 100644 --- a/control/mgmtapi/server.gen.go +++ b/control/mgmtapi/server.gen.go @@ -7,8 +7,8 @@ import ( "fmt" "net/http" - "github.com/deepmap/oapi-codegen/pkg/runtime" "github.com/go-chi/chi/v5" + "github.com/oapi-codegen/runtime" ) // ServerInterface represents all server handlers. @@ -78,6 +78,136 @@ type ServerInterface interface { GetTrcBlob(w http.ResponseWriter, r *http.Request, isd int, base int, serial int) } +// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint. + +type Unimplemented struct{} + +// List the SCION beacons +// (GET /beacons) +func (_ Unimplemented) GetBeacons(w http.ResponseWriter, r *http.Request, params GetBeaconsParams) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the SCION beacon description +// (GET /beacons/{segment-id}) +func (_ Unimplemented) GetBeacon(w http.ResponseWriter, r *http.Request, segmentId SegmentID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the SCION beacon blob +// (GET /beacons/{segment-id}/blob) +func (_ Unimplemented) GetBeaconBlob(w http.ResponseWriter, r *http.Request, segmentId SegmentID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Information about the CA. +// (GET /ca) +func (_ Unimplemented) GetCa(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// List the certificate chains +// (GET /certificates) +func (_ Unimplemented) GetCertificates(w http.ResponseWriter, r *http.Request, params GetCertificatesParams) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the certificate chain +// (GET /certificates/{chain-id}) +func (_ Unimplemented) GetCertificate(w http.ResponseWriter, r *http.Request, chainId ChainID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the certificate chain blob +// (GET /certificates/{chain-id}/blob) +func (_ Unimplemented) GetCertificateBlob(w http.ResponseWriter, r *http.Request, chainId ChainID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Prints the TOML configuration file. +// (GET /config) +func (_ Unimplemented) GetConfig(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Indicate the service health. +// (GET /health) +func (_ Unimplemented) GetHealth(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Basic information page about the control service process. +// (GET /info) +func (_ Unimplemented) GetInfo(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get logging level +// (GET /log/level) +func (_ Unimplemented) GetLogLevel(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Set logging level +// (PUT /log/level) +func (_ Unimplemented) SetLogLevel(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// List the SCION path segments +// (GET /segments) +func (_ Unimplemented) GetSegments(w http.ResponseWriter, r *http.Request, params GetSegmentsParams) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the SCION path segment description +// (GET /segments/{segment-id}) +func (_ Unimplemented) GetSegment(w http.ResponseWriter, r *http.Request, segmentId SegmentID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the SCION path segment blob +// (GET /segments/{segment-id}/blob) +func (_ Unimplemented) GetSegmentBlob(w http.ResponseWriter, r *http.Request, segmentId SegmentID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Prints information about the AS Certificate used to sign the control-plane message. +// (GET /signer) +func (_ Unimplemented) GetSigner(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the certificate chain blob +// (GET /signer/blob) +func (_ Unimplemented) GetSignerChain(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Prints the contents of the AS topology file. +// (GET /topology) +func (_ Unimplemented) GetTopology(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// List the TRCs +// (GET /trcs) +func (_ Unimplemented) GetTrcs(w http.ResponseWriter, r *http.Request, params GetTrcsParams) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the TRC +// (GET /trcs/isd{isd}-b{base}-s{serial}) +func (_ Unimplemented) GetTrc(w http.ResponseWriter, r *http.Request, isd int, base int, serial int) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the TRC blob +// (GET /trcs/isd{isd}-b{base}-s{serial}/blob) +func (_ Unimplemented) GetTrcBlob(w http.ResponseWriter, r *http.Request, isd int, base int, serial int) { + w.WriteHeader(http.StatusNotImplemented) +} + // ServerInterfaceWrapper converts contexts to parameters. type ServerInterfaceWrapper struct { Handler ServerInterface @@ -152,9 +282,9 @@ func (siw *ServerInterfaceWrapper) GetBeacons(w http.ResponseWriter, r *http.Req return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetBeacons(w, r, params) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -178,9 +308,9 @@ func (siw *ServerInterfaceWrapper) GetBeacon(w http.ResponseWriter, r *http.Requ return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetBeacon(w, r, segmentId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -204,9 +334,9 @@ func (siw *ServerInterfaceWrapper) GetBeaconBlob(w http.ResponseWriter, r *http. return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetBeaconBlob(w, r, segmentId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -219,9 +349,9 @@ func (siw *ServerInterfaceWrapper) GetBeaconBlob(w http.ResponseWriter, r *http. func (siw *ServerInterfaceWrapper) GetCa(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCa(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -263,9 +393,9 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificates(w, r, params) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -289,9 +419,9 @@ func (siw *ServerInterfaceWrapper) GetCertificate(w http.ResponseWriter, r *http return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificate(w, r, chainId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -315,9 +445,9 @@ func (siw *ServerInterfaceWrapper) GetCertificateBlob(w http.ResponseWriter, r * return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificateBlob(w, r, chainId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -330,9 +460,9 @@ func (siw *ServerInterfaceWrapper) GetCertificateBlob(w http.ResponseWriter, r * func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetConfig(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -345,9 +475,9 @@ func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Requ func (siw *ServerInterfaceWrapper) GetHealth(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetHealth(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -360,9 +490,9 @@ func (siw *ServerInterfaceWrapper) GetHealth(w http.ResponseWriter, r *http.Requ func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInfo(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -375,9 +505,9 @@ func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Reques func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetLogLevel(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -390,9 +520,9 @@ func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Re func (siw *ServerInterfaceWrapper) SetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetLogLevel(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -426,9 +556,9 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegments(w, r, params) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -452,9 +582,9 @@ func (siw *ServerInterfaceWrapper) GetSegment(w http.ResponseWriter, r *http.Req return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegment(w, r, segmentId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -478,9 +608,9 @@ func (siw *ServerInterfaceWrapper) GetSegmentBlob(w http.ResponseWriter, r *http return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegmentBlob(w, r, segmentId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -493,9 +623,9 @@ func (siw *ServerInterfaceWrapper) GetSegmentBlob(w http.ResponseWriter, r *http func (siw *ServerInterfaceWrapper) GetSigner(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSigner(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -508,9 +638,9 @@ func (siw *ServerInterfaceWrapper) GetSigner(w http.ResponseWriter, r *http.Requ func (siw *ServerInterfaceWrapper) GetSignerChain(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSignerChain(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -523,9 +653,9 @@ func (siw *ServerInterfaceWrapper) GetSignerChain(w http.ResponseWriter, r *http func (siw *ServerInterfaceWrapper) GetTopology(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTopology(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -559,9 +689,9 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcs(w, r, params) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -603,9 +733,9 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrc(w, r, isd, base, serial) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -647,9 +777,9 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcBlob(w, r, isd, base, serial) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -671,16 +801,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshallingParamError struct { +type UnmarshalingParamError struct { ParamName string Err error } -func (e *UnmarshallingParamError) Error() string { - return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshalingParamError) Error() string { + return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshallingParamError) Unwrap() error { +func (e *UnmarshalingParamError) Unwrap() error { return e.Err } diff --git a/control/mgmtapi/spec.gen.go b/control/mgmtapi/spec.gen.go index 8a9c4b2f0..58488deea 100644 --- a/control/mgmtapi/spec.gen.go +++ b/control/mgmtapi/spec.gen.go @@ -100,16 +100,16 @@ var swaggerSpec = []string{ func decodeSpec() ([]byte, error) { zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) if err != nil { - return nil, fmt.Errorf("error base64 decoding spec: %s", err) + return nil, fmt.Errorf("error base64 decoding spec: %w", err) } zr, err := gzip.NewReader(bytes.NewReader(zipped)) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %s", err) + return nil, fmt.Errorf("error decompressing spec: %w", err) } var buf bytes.Buffer _, err = buf.ReadFrom(zr) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %s", err) + return nil, fmt.Errorf("error decompressing spec: %w", err) } return buf.Bytes(), nil @@ -127,7 +127,7 @@ func decodeSpecCached() func() ([]byte, error) { // Constructs a synthetic filesystem for resolving external references when loading openapi specifications. func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { - var res = make(map[string]func() ([]byte, error)) + res := make(map[string]func() ([]byte, error)) if len(pathToFile) > 0 { res[pathToFile] = rawSpec } @@ -141,12 +141,12 @@ func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { // Externally referenced files must be embedded in the corresponding golang packages. // Urls can be supported but this task was out of the scope. func GetSwagger() (swagger *openapi3.T, err error) { - var resolvePath = PathToRawSpec("") + resolvePath := PathToRawSpec("") loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { - var pathToFile = url.String() + pathToFile := url.String() pathToFile = path.Clean(pathToFile) getSpec, ok := resolvePath[pathToFile] if !ok { diff --git a/daemon/mgmtapi/BUILD.bazel b/daemon/mgmtapi/BUILD.bazel index 7d20b0599..5a5414ddb 100644 --- a/daemon/mgmtapi/BUILD.bazel +++ b/daemon/mgmtapi/BUILD.bazel @@ -32,8 +32,8 @@ go_library( "//private/mgmtapi:go_default_library", "//private/mgmtapi/cppki/api:go_default_library", "//private/mgmtapi/segments/api:go_default_library", - "@com_github_deepmap_oapi_codegen//pkg/runtime:go_default_library", # keep "@com_github_getkin_kin_openapi//openapi3:go_default_library", # keep "@com_github_go_chi_chi_v5//:go_default_library", # keep + "@com_github_oapi_codegen_runtime//:go_default_library", # keep ], ) diff --git a/daemon/mgmtapi/client.gen.go b/daemon/mgmtapi/client.gen.go index b6d34cf5e..8979f5110 100644 --- a/daemon/mgmtapi/client.gen.go +++ b/daemon/mgmtapi/client.gen.go @@ -13,7 +13,7 @@ import ( "net/url" "strings" - "github.com/deepmap/oapi-codegen/pkg/runtime" + "github.com/oapi-codegen/runtime" ) // RequestEditorFn is the function signature for the RequestEditor callback function @@ -107,7 +107,7 @@ type ClientInterface interface { // GetLogLevel request GetLogLevel(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - // SetLogLevel request with any body + // SetLogLevelWithBody request with any body SetLogLevelWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) SetLogLevel(ctx context.Context, body SetLogLevelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -318,58 +318,60 @@ func NewGetCertificatesRequest(server string, params *GetCertificatesParams) (*h return nil, err } - queryValues := queryURL.Query() + if params != nil { + queryValues := queryURL.Query() - if params.IsdAs != nil { + if params.IsdAs != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "isd_as", runtime.ParamLocationQuery, *params.IsdAs); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "isd_as", runtime.ParamLocationQuery, *params.IsdAs); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - - } - if params.ValidAt != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "valid_at", runtime.ParamLocationQuery, *params.ValidAt); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.ValidAt != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "valid_at", runtime.ParamLocationQuery, *params.ValidAt); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - } - - if params.All != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.All != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } + } + queryURL.RawQuery = queryValues.Encode() } - queryURL.RawQuery = queryValues.Encode() - req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -586,42 +588,44 @@ func NewGetSegmentsRequest(server string, params *GetSegmentsParams) (*http.Requ return nil, err } - queryValues := queryURL.Query() + if params != nil { + queryValues := queryURL.Query() - if params.StartIsdAs != nil { + if params.StartIsdAs != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "start_isd_as", runtime.ParamLocationQuery, *params.StartIsdAs); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "start_isd_as", runtime.ParamLocationQuery, *params.StartIsdAs); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - - } - if params.EndIsdAs != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "end_isd_as", runtime.ParamLocationQuery, *params.EndIsdAs); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.EndIsdAs != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "end_isd_as", runtime.ParamLocationQuery, *params.EndIsdAs); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } + } + queryURL.RawQuery = queryValues.Encode() } - queryURL.RawQuery = queryValues.Encode() - req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -717,42 +721,44 @@ func NewGetTrcsRequest(server string, params *GetTrcsParams) (*http.Request, err return nil, err } - queryValues := queryURL.Query() + if params != nil { + queryValues := queryURL.Query() - if params.Isd != nil { + if params.Isd != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "isd", runtime.ParamLocationQuery, *params.Isd); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "isd", runtime.ParamLocationQuery, *params.Isd); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - } - - if params.All != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.All != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } + } + queryURL.RawQuery = queryValues.Encode() } - queryURL.RawQuery = queryValues.Encode() - req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -900,53 +906,53 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // GetCertificates request + // GetCertificatesWithResponse request GetCertificatesWithResponse(ctx context.Context, params *GetCertificatesParams, reqEditors ...RequestEditorFn) (*GetCertificatesResponse, error) - // GetCertificate request + // GetCertificateWithResponse request GetCertificateWithResponse(ctx context.Context, chainId ChainID, reqEditors ...RequestEditorFn) (*GetCertificateResponse, error) - // GetCertificateBlob request + // GetCertificateBlobWithResponse request GetCertificateBlobWithResponse(ctx context.Context, chainId ChainID, reqEditors ...RequestEditorFn) (*GetCertificateBlobResponse, error) - // GetConfig request + // GetConfigWithResponse request GetConfigWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetConfigResponse, error) - // GetInfo request + // GetInfoWithResponse request GetInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetInfoResponse, error) - // GetLogLevel request + // GetLogLevelWithResponse request GetLogLevelWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetLogLevelResponse, error) - // SetLogLevel request with any body + // SetLogLevelWithBodyWithResponse request with any body SetLogLevelWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetLogLevelResponse, error) SetLogLevelWithResponse(ctx context.Context, body SetLogLevelJSONRequestBody, reqEditors ...RequestEditorFn) (*SetLogLevelResponse, error) - // GetSegments request + // GetSegmentsWithResponse request GetSegmentsWithResponse(ctx context.Context, params *GetSegmentsParams, reqEditors ...RequestEditorFn) (*GetSegmentsResponse, error) - // GetSegment request + // GetSegmentWithResponse request GetSegmentWithResponse(ctx context.Context, segmentId SegmentID, reqEditors ...RequestEditorFn) (*GetSegmentResponse, error) - // GetSegmentBlob request + // GetSegmentBlobWithResponse request GetSegmentBlobWithResponse(ctx context.Context, segmentId SegmentID, reqEditors ...RequestEditorFn) (*GetSegmentBlobResponse, error) - // GetTrcs request + // GetTrcsWithResponse request GetTrcsWithResponse(ctx context.Context, params *GetTrcsParams, reqEditors ...RequestEditorFn) (*GetTrcsResponse, error) - // GetTrc request + // GetTrcWithResponse request GetTrcWithResponse(ctx context.Context, isd int, base int, serial int, reqEditors ...RequestEditorFn) (*GetTrcResponse, error) - // GetTrcBlob request + // GetTrcBlobWithResponse request GetTrcBlobWithResponse(ctx context.Context, isd int, base int, serial int, reqEditors ...RequestEditorFn) (*GetTrcBlobResponse, error) } type GetCertificatesResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *[]ChainBrief - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *[]ChainBrief + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -966,10 +972,10 @@ func (r GetCertificatesResponse) StatusCode() int { } type GetCertificateResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *Chain - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *Chain + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -989,9 +995,9 @@ func (r GetCertificateResponse) StatusCode() int { } type GetCertificateBlobResponse struct { - Body []byte - HTTPResponse *http.Response - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -1013,7 +1019,7 @@ func (r GetCertificateBlobResponse) StatusCode() int { type GetConfigResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1035,7 +1041,7 @@ func (r GetConfigResponse) StatusCode() int { type GetInfoResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1058,7 +1064,7 @@ type GetLogLevelResponse struct { Body []byte HTTPResponse *http.Response JSON200 *LogLevel - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1081,7 +1087,7 @@ type SetLogLevelResponse struct { Body []byte HTTPResponse *http.Response JSON200 *LogLevel - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1101,10 +1107,10 @@ func (r SetLogLevelResponse) StatusCode() int { } type GetSegmentsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *[]SegmentBrief - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *[]SegmentBrief + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -1124,10 +1130,10 @@ func (r GetSegmentsResponse) StatusCode() int { } type GetSegmentResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *Segment - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *Segment + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -1147,9 +1153,9 @@ func (r GetSegmentResponse) StatusCode() int { } type GetSegmentBlobResponse struct { - Body []byte - HTTPResponse *http.Response - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -1172,7 +1178,7 @@ type GetTrcsResponse struct { Body []byte HTTPResponse *http.Response JSON200 *[]TRCBrief - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1195,7 +1201,7 @@ type GetTrcResponse struct { Body []byte HTTPResponse *http.Response JSON200 *TRC - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1217,7 +1223,7 @@ func (r GetTrcResponse) StatusCode() int { type GetTrcBlobResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -1387,7 +1393,7 @@ func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -1420,7 +1426,7 @@ func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, e if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -1446,7 +1452,7 @@ func ParseGetCertificateBlobResponse(rsp *http.Response) (*GetCertificateBlobRes if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -1468,7 +1474,7 @@ func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -1494,7 +1500,7 @@ func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -1527,7 +1533,7 @@ func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -1560,7 +1566,7 @@ func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -1597,7 +1603,7 @@ func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -1630,7 +1636,7 @@ func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -1656,7 +1662,7 @@ func ParseGetSegmentBlobResponse(rsp *http.Response) (*GetSegmentBlobResponse, e if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -1685,7 +1691,7 @@ func ParseGetTrcsResponse(rsp *http.Response) (*GetTrcsResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -1718,7 +1724,7 @@ func ParseGetTrcResponse(rsp *http.Response) (*GetTrcResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -1744,7 +1750,7 @@ func ParseGetTrcBlobResponse(rsp *http.Response) (*GetTrcBlobResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/daemon/mgmtapi/server.gen.go b/daemon/mgmtapi/server.gen.go index d7562b91b..d340dcdc7 100644 --- a/daemon/mgmtapi/server.gen.go +++ b/daemon/mgmtapi/server.gen.go @@ -7,8 +7,8 @@ import ( "fmt" "net/http" - "github.com/deepmap/oapi-codegen/pkg/runtime" "github.com/go-chi/chi/v5" + "github.com/oapi-codegen/runtime" ) // ServerInterface represents all server handlers. @@ -54,6 +54,88 @@ type ServerInterface interface { GetTrcBlob(w http.ResponseWriter, r *http.Request, isd int, base int, serial int) } +// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint. + +type Unimplemented struct{} + +// List the certificate chains +// (GET /certificates) +func (_ Unimplemented) GetCertificates(w http.ResponseWriter, r *http.Request, params GetCertificatesParams) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the certificate chain +// (GET /certificates/{chain-id}) +func (_ Unimplemented) GetCertificate(w http.ResponseWriter, r *http.Request, chainId ChainID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the certificate chain blob +// (GET /certificates/{chain-id}/blob) +func (_ Unimplemented) GetCertificateBlob(w http.ResponseWriter, r *http.Request, chainId ChainID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Prints the TOML configuration file. +// (GET /config) +func (_ Unimplemented) GetConfig(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Basic information page about the control service process. +// (GET /info) +func (_ Unimplemented) GetInfo(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get logging level +// (GET /log/level) +func (_ Unimplemented) GetLogLevel(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Set logging level +// (PUT /log/level) +func (_ Unimplemented) SetLogLevel(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// List the SCION path segments +// (GET /segments) +func (_ Unimplemented) GetSegments(w http.ResponseWriter, r *http.Request, params GetSegmentsParams) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the SCION path segment description +// (GET /segments/{segment-id}) +func (_ Unimplemented) GetSegment(w http.ResponseWriter, r *http.Request, segmentId SegmentID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the SCION path segment blob +// (GET /segments/{segment-id}/blob) +func (_ Unimplemented) GetSegmentBlob(w http.ResponseWriter, r *http.Request, segmentId SegmentID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// List the TRCs +// (GET /trcs) +func (_ Unimplemented) GetTrcs(w http.ResponseWriter, r *http.Request, params GetTrcsParams) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the TRC +// (GET /trcs/isd{isd}-b{base}-s{serial}) +func (_ Unimplemented) GetTrc(w http.ResponseWriter, r *http.Request, isd int, base int, serial int) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the TRC blob +// (GET /trcs/isd{isd}-b{base}-s{serial}/blob) +func (_ Unimplemented) GetTrcBlob(w http.ResponseWriter, r *http.Request, isd int, base int, serial int) { + w.WriteHeader(http.StatusNotImplemented) +} + // ServerInterfaceWrapper converts contexts to parameters. type ServerInterfaceWrapper struct { Handler ServerInterface @@ -96,9 +178,9 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificates(w, r, params) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -122,9 +204,9 @@ func (siw *ServerInterfaceWrapper) GetCertificate(w http.ResponseWriter, r *http return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificate(w, r, chainId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -148,9 +230,9 @@ func (siw *ServerInterfaceWrapper) GetCertificateBlob(w http.ResponseWriter, r * return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificateBlob(w, r, chainId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -163,9 +245,9 @@ func (siw *ServerInterfaceWrapper) GetCertificateBlob(w http.ResponseWriter, r * func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetConfig(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -178,9 +260,9 @@ func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Requ func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInfo(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -193,9 +275,9 @@ func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Reques func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetLogLevel(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -208,9 +290,9 @@ func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Re func (siw *ServerInterfaceWrapper) SetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetLogLevel(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -244,9 +326,9 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegments(w, r, params) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -270,9 +352,9 @@ func (siw *ServerInterfaceWrapper) GetSegment(w http.ResponseWriter, r *http.Req return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegment(w, r, segmentId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -296,9 +378,9 @@ func (siw *ServerInterfaceWrapper) GetSegmentBlob(w http.ResponseWriter, r *http return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegmentBlob(w, r, segmentId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -332,9 +414,9 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcs(w, r, params) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -376,9 +458,9 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrc(w, r, isd, base, serial) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -420,9 +502,9 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcBlob(w, r, isd, base, serial) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -444,16 +526,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshallingParamError struct { +type UnmarshalingParamError struct { ParamName string Err error } -func (e *UnmarshallingParamError) Error() string { - return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshalingParamError) Error() string { + return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshallingParamError) Unwrap() error { +func (e *UnmarshalingParamError) Unwrap() error { return e.Err } diff --git a/daemon/mgmtapi/spec.gen.go b/daemon/mgmtapi/spec.gen.go index b7982b4e3..743bd4dd3 100644 --- a/daemon/mgmtapi/spec.gen.go +++ b/daemon/mgmtapi/spec.gen.go @@ -75,16 +75,16 @@ var swaggerSpec = []string{ func decodeSpec() ([]byte, error) { zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) if err != nil { - return nil, fmt.Errorf("error base64 decoding spec: %s", err) + return nil, fmt.Errorf("error base64 decoding spec: %w", err) } zr, err := gzip.NewReader(bytes.NewReader(zipped)) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %s", err) + return nil, fmt.Errorf("error decompressing spec: %w", err) } var buf bytes.Buffer _, err = buf.ReadFrom(zr) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %s", err) + return nil, fmt.Errorf("error decompressing spec: %w", err) } return buf.Bytes(), nil @@ -102,7 +102,7 @@ func decodeSpecCached() func() ([]byte, error) { // Constructs a synthetic filesystem for resolving external references when loading openapi specifications. func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { - var res = make(map[string]func() ([]byte, error)) + res := make(map[string]func() ([]byte, error)) if len(pathToFile) > 0 { res[pathToFile] = rawSpec } @@ -116,12 +116,12 @@ func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { // Externally referenced files must be embedded in the corresponding golang packages. // Urls can be supported but this task was out of the scope. func GetSwagger() (swagger *openapi3.T, err error) { - var resolvePath = PathToRawSpec("") + resolvePath := PathToRawSpec("") loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { - var pathToFile = url.String() + pathToFile := url.String() pathToFile = path.Clean(pathToFile) getSpec, ok := resolvePath[pathToFile] if !ok { diff --git a/dispatcher/mgmtapi/client.gen.go b/dispatcher/mgmtapi/client.gen.go index d87b18ca4..d61cd66f1 100644 --- a/dispatcher/mgmtapi/client.gen.go +++ b/dispatcher/mgmtapi/client.gen.go @@ -96,7 +96,7 @@ type ClientInterface interface { // GetLogLevel request GetLogLevel(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - // SetLogLevel request with any body + // SetLogLevelWithBody request with any body SetLogLevelWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) SetLogLevel(ctx context.Context, body SetLogLevelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -326,16 +326,16 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // GetConfig request + // GetConfigWithResponse request GetConfigWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetConfigResponse, error) - // GetInfo request + // GetInfoWithResponse request GetInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetInfoResponse, error) - // GetLogLevel request + // GetLogLevelWithResponse request GetLogLevelWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetLogLevelResponse, error) - // SetLogLevel request with any body + // SetLogLevelWithBodyWithResponse request with any body SetLogLevelWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetLogLevelResponse, error) SetLogLevelWithResponse(ctx context.Context, body SetLogLevelJSONRequestBody, reqEditors ...RequestEditorFn) (*SetLogLevelResponse, error) @@ -344,7 +344,7 @@ type ClientWithResponsesInterface interface { type GetConfigResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -366,7 +366,7 @@ func (r GetConfigResponse) StatusCode() int { type GetInfoResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -389,7 +389,7 @@ type GetLogLevelResponse struct { Body []byte HTTPResponse *http.Response JSON200 *LogLevel - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -412,7 +412,7 @@ type SetLogLevelResponse struct { Body []byte HTTPResponse *http.Response JSON200 *LogLevel - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -490,7 +490,7 @@ func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -516,7 +516,7 @@ func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -549,7 +549,7 @@ func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -582,7 +582,7 @@ func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/dispatcher/mgmtapi/server.gen.go b/dispatcher/mgmtapi/server.gen.go index c6b1ffa8c..4799ade91 100644 --- a/dispatcher/mgmtapi/server.gen.go +++ b/dispatcher/mgmtapi/server.gen.go @@ -26,6 +26,34 @@ type ServerInterface interface { SetLogLevel(w http.ResponseWriter, r *http.Request) } +// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint. + +type Unimplemented struct{} + +// Prints the TOML configuration file. +// (GET /config) +func (_ Unimplemented) GetConfig(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Basic information page about the control service process. +// (GET /info) +func (_ Unimplemented) GetInfo(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get logging level +// (GET /log/level) +func (_ Unimplemented) GetLogLevel(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Set logging level +// (PUT /log/level) +func (_ Unimplemented) SetLogLevel(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + // ServerInterfaceWrapper converts contexts to parameters. type ServerInterfaceWrapper struct { Handler ServerInterface @@ -39,9 +67,9 @@ type MiddlewareFunc func(http.Handler) http.Handler func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetConfig(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -54,9 +82,9 @@ func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Requ func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInfo(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -69,9 +97,9 @@ func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Reques func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetLogLevel(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -84,9 +112,9 @@ func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Re func (siw *ServerInterfaceWrapper) SetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetLogLevel(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -108,16 +136,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshallingParamError struct { +type UnmarshalingParamError struct { ParamName string Err error } -func (e *UnmarshallingParamError) Error() string { - return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshalingParamError) Error() string { + return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshallingParamError) Unwrap() error { +func (e *UnmarshalingParamError) Unwrap() error { return e.Err } diff --git a/dispatcher/mgmtapi/spec.gen.go b/dispatcher/mgmtapi/spec.gen.go index 1beab4eb2..26d83dc66 100644 --- a/dispatcher/mgmtapi/spec.gen.go +++ b/dispatcher/mgmtapi/spec.gen.go @@ -36,16 +36,16 @@ var swaggerSpec = []string{ func decodeSpec() ([]byte, error) { zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) if err != nil { - return nil, fmt.Errorf("error base64 decoding spec: %s", err) + return nil, fmt.Errorf("error base64 decoding spec: %w", err) } zr, err := gzip.NewReader(bytes.NewReader(zipped)) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %s", err) + return nil, fmt.Errorf("error decompressing spec: %w", err) } var buf bytes.Buffer _, err = buf.ReadFrom(zr) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %s", err) + return nil, fmt.Errorf("error decompressing spec: %w", err) } return buf.Bytes(), nil @@ -63,7 +63,7 @@ func decodeSpecCached() func() ([]byte, error) { // Constructs a synthetic filesystem for resolving external references when loading openapi specifications. func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { - var res = make(map[string]func() ([]byte, error)) + res := make(map[string]func() ([]byte, error)) if len(pathToFile) > 0 { res[pathToFile] = rawSpec } @@ -77,12 +77,12 @@ func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { // Externally referenced files must be embedded in the corresponding golang packages. // Urls can be supported but this task was out of the scope. func GetSwagger() (swagger *openapi3.T, err error) { - var resolvePath = PathToRawSpec("") + resolvePath := PathToRawSpec("") loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { - var pathToFile = url.String() + pathToFile := url.String() pathToFile = path.Clean(pathToFile) getSpec, ok := resolvePath[pathToFile] if !ok { diff --git a/gateway/mgmtapi/BUILD.bazel b/gateway/mgmtapi/BUILD.bazel index ecf7d7a5c..1aad622f3 100644 --- a/gateway/mgmtapi/BUILD.bazel +++ b/gateway/mgmtapi/BUILD.bazel @@ -30,8 +30,8 @@ go_library( visibility = ["//visibility:public"], deps = [ "//private/mgmtapi:go_default_library", - "@com_github_deepmap_oapi_codegen//pkg/runtime:go_default_library", # keep "@com_github_getkin_kin_openapi//openapi3:go_default_library", # keep "@com_github_go_chi_chi_v5//:go_default_library", # keep + "@com_github_oapi_codegen_runtime//:go_default_library", # keep ], ) diff --git a/gateway/mgmtapi/client.gen.go b/gateway/mgmtapi/client.gen.go index d87b18ca4..d61cd66f1 100644 --- a/gateway/mgmtapi/client.gen.go +++ b/gateway/mgmtapi/client.gen.go @@ -96,7 +96,7 @@ type ClientInterface interface { // GetLogLevel request GetLogLevel(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - // SetLogLevel request with any body + // SetLogLevelWithBody request with any body SetLogLevelWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) SetLogLevel(ctx context.Context, body SetLogLevelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -326,16 +326,16 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // GetConfig request + // GetConfigWithResponse request GetConfigWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetConfigResponse, error) - // GetInfo request + // GetInfoWithResponse request GetInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetInfoResponse, error) - // GetLogLevel request + // GetLogLevelWithResponse request GetLogLevelWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetLogLevelResponse, error) - // SetLogLevel request with any body + // SetLogLevelWithBodyWithResponse request with any body SetLogLevelWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetLogLevelResponse, error) SetLogLevelWithResponse(ctx context.Context, body SetLogLevelJSONRequestBody, reqEditors ...RequestEditorFn) (*SetLogLevelResponse, error) @@ -344,7 +344,7 @@ type ClientWithResponsesInterface interface { type GetConfigResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -366,7 +366,7 @@ func (r GetConfigResponse) StatusCode() int { type GetInfoResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -389,7 +389,7 @@ type GetLogLevelResponse struct { Body []byte HTTPResponse *http.Response JSON200 *LogLevel - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -412,7 +412,7 @@ type SetLogLevelResponse struct { Body []byte HTTPResponse *http.Response JSON200 *LogLevel - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -490,7 +490,7 @@ func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -516,7 +516,7 @@ func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -549,7 +549,7 @@ func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -582,7 +582,7 @@ func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/gateway/mgmtapi/server.gen.go b/gateway/mgmtapi/server.gen.go index c6b1ffa8c..4799ade91 100644 --- a/gateway/mgmtapi/server.gen.go +++ b/gateway/mgmtapi/server.gen.go @@ -26,6 +26,34 @@ type ServerInterface interface { SetLogLevel(w http.ResponseWriter, r *http.Request) } +// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint. + +type Unimplemented struct{} + +// Prints the TOML configuration file. +// (GET /config) +func (_ Unimplemented) GetConfig(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Basic information page about the control service process. +// (GET /info) +func (_ Unimplemented) GetInfo(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get logging level +// (GET /log/level) +func (_ Unimplemented) GetLogLevel(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Set logging level +// (PUT /log/level) +func (_ Unimplemented) SetLogLevel(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + // ServerInterfaceWrapper converts contexts to parameters. type ServerInterfaceWrapper struct { Handler ServerInterface @@ -39,9 +67,9 @@ type MiddlewareFunc func(http.Handler) http.Handler func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetConfig(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -54,9 +82,9 @@ func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Requ func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInfo(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -69,9 +97,9 @@ func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Reques func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetLogLevel(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -84,9 +112,9 @@ func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Re func (siw *ServerInterfaceWrapper) SetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetLogLevel(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -108,16 +136,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshallingParamError struct { +type UnmarshalingParamError struct { ParamName string Err error } -func (e *UnmarshallingParamError) Error() string { - return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshalingParamError) Error() string { + return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshallingParamError) Unwrap() error { +func (e *UnmarshalingParamError) Unwrap() error { return e.Err } diff --git a/gateway/mgmtapi/spec.gen.go b/gateway/mgmtapi/spec.gen.go index ca1dde80c..74a79c8a7 100644 --- a/gateway/mgmtapi/spec.gen.go +++ b/gateway/mgmtapi/spec.gen.go @@ -36,16 +36,16 @@ var swaggerSpec = []string{ func decodeSpec() ([]byte, error) { zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) if err != nil { - return nil, fmt.Errorf("error base64 decoding spec: %s", err) + return nil, fmt.Errorf("error base64 decoding spec: %w", err) } zr, err := gzip.NewReader(bytes.NewReader(zipped)) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %s", err) + return nil, fmt.Errorf("error decompressing spec: %w", err) } var buf bytes.Buffer _, err = buf.ReadFrom(zr) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %s", err) + return nil, fmt.Errorf("error decompressing spec: %w", err) } return buf.Bytes(), nil @@ -63,7 +63,7 @@ func decodeSpecCached() func() ([]byte, error) { // Constructs a synthetic filesystem for resolving external references when loading openapi specifications. func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { - var res = make(map[string]func() ([]byte, error)) + res := make(map[string]func() ([]byte, error)) if len(pathToFile) > 0 { res[pathToFile] = rawSpec } @@ -77,12 +77,12 @@ func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { // Externally referenced files must be embedded in the corresponding golang packages. // Urls can be supported but this task was out of the scope. func GetSwagger() (swagger *openapi3.T, err error) { - var resolvePath = PathToRawSpec("") + resolvePath := PathToRawSpec("") loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { - var pathToFile = url.String() + pathToFile := url.String() pathToFile = path.Clean(pathToFile) getSpec, ok := resolvePath[pathToFile] if !ok { diff --git a/go.mod b/go.mod index 67f8b840f..77f168f21 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,9 @@ require ( github.com/bazelbuild/rules_go v0.38.1 github.com/buildkite/go-buildkite/v2 v2.9.0 github.com/dchest/cmac v1.0.0 - github.com/deepmap/oapi-codegen v1.12.5-0.20230221180206-2b52cd58cf5b + github.com/deepmap/oapi-codegen/v2 v2.0.0 github.com/fatih/color v1.14.1 - github.com/getkin/kin-openapi v0.114.0 + github.com/getkin/kin-openapi v0.118.0 github.com/go-chi/chi/v5 v5.0.8 github.com/go-chi/cors v1.2.1 github.com/golang/mock v1.6.0 @@ -21,8 +21,9 @@ require ( github.com/hashicorp/golang-lru v0.6.0 github.com/iancoleman/strcase v0.2.0 github.com/lestrrat-go/jwx v1.2.25 - github.com/mattn/go-isatty v0.0.17 + github.com/mattn/go-isatty v0.0.19 github.com/mattn/go-sqlite3 v1.14.17 + github.com/oapi-codegen/runtime v1.0.0 github.com/olekukonko/tablewriter v0.0.5 github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.1-0.20180815053127-5633e0862627+incompatible @@ -37,16 +38,16 @@ require ( github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.15.0 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.4 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/vishvananda/netlink v1.2.1-beta.2 go.uber.org/goleak v1.2.1 go.uber.org/zap v1.24.0 go4.org/netipx v0.0.0-20230125063823-8449b0a6169f - golang.org/x/crypto v0.6.0 - golang.org/x/net v0.10.0 + golang.org/x/crypto v0.12.0 + golang.org/x/net v0.14.0 golang.org/x/sync v0.3.0 - golang.org/x/tools v0.9.1 + golang.org/x/tools v0.12.0 google.golang.org/grpc v1.57.2 google.golang.org/grpc/examples v0.0.0-20230222033013-5353eaa44095 google.golang.org/protobuf v1.31.0 @@ -69,10 +70,10 @@ require ( github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/swag v0.21.1 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/goccy/go-json v0.9.11 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/google/go-querystring v1.0.1-0.20190318165438-c8c88dbee036 // indirect github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect @@ -93,7 +94,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/onsi/ginkgo/v2 v2.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/pelletier/go-toml/v2 v2.0.9 // indirect github.com/perimeterx/marshmallow v1.1.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect @@ -112,9 +113,9 @@ require ( go.uber.org/mock v0.3.0 // indirect go.uber.org/multierr v1.8.0 // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect - golang.org/x/mod v0.11.0 // indirect + golang.org/x/mod v0.12.0 // indirect golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/text v0.13.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 8efbd3866..c53bec95f 100644 --- a/go.sum +++ b/go.sum @@ -89,8 +89,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/deepmap/oapi-codegen v1.12.5-0.20230221180206-2b52cd58cf5b h1:LDDxTtOtlGKTubzsuonFRmhMgP5zfWmM+G3Ql948TAs= -github.com/deepmap/oapi-codegen v1.12.5-0.20230221180206-2b52cd58cf5b/go.mod h1:Oq/fBIJxL5rD6wZen0I3a6yXCwh7Fl0i8d5e4kYYA8c= +github.com/deepmap/oapi-codegen/v2 v2.0.0 h1:3TS7w3r+XnjKFXcbFbc16pTWzfTy0OLPkCsutEHjWDA= +github.com/deepmap/oapi-codegen/v2 v2.0.0/go.mod h1:7zR+ZL3WzLeCkr2k8oWTxEa0v8y/F25ane0l6A5UjLA= github.com/docker/cli v20.10.20+incompatible h1:lWQbHSHUFs7KraSN2jOJK7zbMS2jNCHI4mt4xUFUVQ4= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/docker v20.10.20+incompatible h1:kH9tx6XO+359d+iAkumyKDc5Q1kOwPuAUaeri48nD6E= @@ -108,8 +108,8 @@ github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8Wlg github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/getkin/kin-openapi v0.114.0 h1:ar7QiJpDdlR+zSyPjrLf8mNnpoFP/lI90XcywMCFNe8= -github.com/getkin/kin-openapi v0.114.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc= +github.com/getkin/kin-openapi v0.118.0 h1:z43njxPmJ7TaPpMSCQb7PN0dEYno4tyBPQcrFdHoLuM= +github.com/getkin/kin-openapi v0.118.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc= github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= @@ -137,8 +137,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4 github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -211,8 +211,8 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -257,7 +257,7 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -290,8 +290,8 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= @@ -311,6 +311,8 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwd github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oapi-codegen/runtime v1.0.0 h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo= +github.com/oapi-codegen/runtime v1.0.0/go.mod h1:LmCUMQuPB4M/nLXilQXhHw+BLZdDb18B34OO356yJ/A= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= @@ -325,8 +327,8 @@ github.com/patrickmn/go-cache v2.1.1-0.20180815053127-5633e0862627+incompatible github.com/patrickmn/go-cache v2.1.1-0.20180815053127-5633e0862627+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= +github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw= github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -411,8 +413,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= @@ -421,8 +424,8 @@ github.com/uber/jaeger-lib v2.0.0+incompatible h1:iMSCV0rmXEogjNWPh2D0xk9YVKvrtG github.com/uber/jaeger-lib v2.0.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= -github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= @@ -464,8 +467,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -491,6 +494,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -502,8 +506,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= -golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -542,8 +546,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -619,6 +623,7 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -631,8 +636,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -687,8 +692,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= +golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/go_deps.bzl b/go_deps.bzl index f1030d3e3..20859e8d1 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -25,6 +25,12 @@ def go_deps(): sum = "h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=", version = "v0.0.0-20190924025748-f65c72e2690d", ) + go_repository( + name = "com_github_andybalholm_brotli", + importpath = "github.com/andybalholm/brotli", + sum = "h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=", + version = "v1.0.5", + ) go_repository( name = "com_github_antlr_antlr4_runtime_go_antlr", importpath = "github.com/antlr/antlr4/runtime/Go/antlr", @@ -43,6 +49,12 @@ def go_deps(): sum = "h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q=", version = "v0.4.0", ) + go_repository( + name = "com_github_aymerick_douceur", + importpath = "github.com/aymerick/douceur", + sum = "h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=", + version = "v0.2.0", + ) go_repository( name = "com_github_azure_go_ansiterm", importpath = "github.com/Azure/go-ansiterm", @@ -82,8 +94,8 @@ def go_deps(): go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", - sum = "h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=", - version = "v0.4.1", + sum = "h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=", + version = "v1.3.2", ) go_repository( name = "com_github_burntsushi_xgb", @@ -91,6 +103,12 @@ def go_deps(): sum = "h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=", version = "v0.0.0-20160522181843-27f122750802", ) + go_repository( + name = "com_github_bytedance_sonic", + importpath = "github.com/bytedance/sonic", + sum = "h1:uNSnscRapXTwUgTyOF0GVljYD08p9X/Lbr9MweSV3V0=", + version = "v1.10.0-rc3", + ) go_repository( name = "com_github_cenkalti_backoff", importpath = "github.com/cenkalti/backoff", @@ -109,6 +127,18 @@ def go_deps(): sum = "h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=", version = "v2.2.0", ) + go_repository( + name = "com_github_chenzhuoyu_base64x", + importpath = "github.com/chenzhuoyu/base64x", + sum = "h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=", + version = "v0.0.0-20230717121745-296ad89f973d", + ) + go_repository( + name = "com_github_chenzhuoyu_iasm", + importpath = "github.com/chenzhuoyu/iasm", + sum = "h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=", + version = "v0.9.0", + ) go_repository( name = "com_github_chzyer_logex", importpath = "github.com/chzyer/logex", @@ -133,6 +163,18 @@ def go_deps(): sum = "h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=", version = "v0.3.4", ) + go_repository( + name = "com_github_cloudykit_fastprinter", + importpath = "github.com/CloudyKit/fastprinter", + sum = "h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=", + version = "v0.0.0-20200109182630-33d98a066a53", + ) + go_repository( + name = "com_github_cloudykit_jet_v6", + importpath = "github.com/CloudyKit/jet/v6", + sum = "h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME=", + version = "v6.2.0", + ) go_repository( name = "com_github_cncf_udpa_go", importpath = "github.com/cncf/udpa/go", @@ -206,10 +248,10 @@ def go_deps(): version = "v4.0.1", ) go_repository( - name = "com_github_deepmap_oapi_codegen", - importpath = "github.com/deepmap/oapi-codegen", - sum = "h1:LDDxTtOtlGKTubzsuonFRmhMgP5zfWmM+G3Ql948TAs=", - version = "v1.12.5-0.20230221180206-2b52cd58cf5b", + name = "com_github_deepmap_oapi_codegen_v2", + importpath = "github.com/deepmap/oapi-codegen/v2", + sum = "h1:3TS7w3r+XnjKFXcbFbc16pTWzfTy0OLPkCsutEHjWDA=", + version = "v2.0.0", ) go_repository( name = "com_github_docker_cli", @@ -277,6 +319,18 @@ def go_deps(): sum = "h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=", version = "v1.14.1", ) + go_repository( + name = "com_github_fatih_structs", + importpath = "github.com/fatih/structs", + sum = "h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=", + version = "v1.1.0", + ) + go_repository( + name = "com_github_flosch_pongo2_v4", + importpath = "github.com/flosch/pongo2/v4", + sum = "h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=", + version = "v4.0.2", + ) go_repository( name = "com_github_francoispqt_gojay", importpath = "github.com/francoispqt/gojay", @@ -295,11 +349,17 @@ def go_deps(): sum = "h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=", version = "v1.6.0", ) + go_repository( + name = "com_github_gabriel_vasile_mimetype", + importpath = "github.com/gabriel-vasile/mimetype", + sum = "h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=", + version = "v1.4.2", + ) go_repository( name = "com_github_getkin_kin_openapi", importpath = "github.com/getkin/kin-openapi", - sum = "h1:ar7QiJpDdlR+zSyPjrLf8mNnpoFP/lI90XcywMCFNe8=", - version = "v0.114.0", + sum = "h1:z43njxPmJ7TaPpMSCQb7PN0dEYno4tyBPQcrFdHoLuM=", + version = "v0.118.0", ) go_repository( name = "com_github_gin_contrib_sse", @@ -310,8 +370,8 @@ def go_deps(): go_repository( name = "com_github_gin_gonic_gin", importpath = "github.com/gin-gonic/gin", - sum = "h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=", - version = "v1.8.2", + sum = "h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=", + version = "v1.9.1", ) go_repository( name = "com_github_go_chi_chi_v5", @@ -376,20 +436,20 @@ def go_deps(): go_repository( name = "com_github_go_playground_locales", importpath = "github.com/go-playground/locales", - sum = "h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=", - version = "v0.14.0", + sum = "h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=", + version = "v0.14.1", ) go_repository( name = "com_github_go_playground_universal_translator", importpath = "github.com/go-playground/universal-translator", - sum = "h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=", - version = "v0.18.0", + sum = "h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=", + version = "v0.18.1", ) go_repository( name = "com_github_go_playground_validator_v10", importpath = "github.com/go-playground/validator/v10", - sum = "h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=", - version = "v10.11.1", + sum = "h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k=", + version = "v10.14.1", ) go_repository( name = "com_github_go_stack_stack", @@ -412,8 +472,8 @@ def go_deps(): go_repository( name = "com_github_goccy_go_json", importpath = "github.com/goccy/go-json", - sum = "h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=", - version = "v0.9.11", + sum = "h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=", + version = "v0.10.2", ) go_repository( name = "com_github_gogo_protobuf", @@ -433,12 +493,6 @@ def go_deps(): sum = "h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=", version = "v0.0.0-20210331224755-41bb18bfe9da", ) - go_repository( - name = "com_github_golang_jwt_jwt", - importpath = "github.com/golang-jwt/jwt", - sum = "h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=", - version = "v3.2.2+incompatible", - ) go_repository( name = "com_github_golang_mock", importpath = "github.com/golang/mock", @@ -452,10 +506,16 @@ def go_deps(): version = "v1.5.3", ) go_repository( - name = "com_github_golangci_lint_1", - importpath = "github.com/golangci/lint-1", - sum = "h1:utua3L2IbQJmauC5IXdEA547bcoU5dozgQAfc8Onsg4=", - version = "v0.0.0-20181222135242-d2cdd8c08219", + name = "com_github_golang_snappy", + importpath = "github.com/golang/snappy", + sum = "h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=", + version = "v0.0.4", + ) + go_repository( + name = "com_github_gomarkdown_markdown", + importpath = "github.com/gomarkdown/markdown", + sum = "h1:uK3X/2mt4tbSGoHvbLBHUny7CKiuwUip3MArtukol4E=", + version = "v0.0.0-20230716120725-531d2d74bc12", ) go_repository( name = "com_github_google_btree", @@ -520,8 +580,8 @@ def go_deps(): go_repository( name = "com_github_google_uuid", importpath = "github.com/google/uuid", - sum = "h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=", - version = "v1.3.0", + sum = "h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=", + version = "v1.3.1", ) go_repository( name = "com_github_googleapis_enterprise_certificate_proxy", @@ -547,6 +607,12 @@ def go_deps(): sum = "h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=", version = "v0.0.0-20181017120253-0766667cb4d1", ) + go_repository( + name = "com_github_gorilla_css", + importpath = "github.com/gorilla/css", + sum = "h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=", + version = "v1.0.0", + ) go_repository( name = "com_github_gorilla_mux", importpath = "github.com/gorilla/mux", @@ -643,6 +709,18 @@ def go_deps(): sum = "h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=", version = "v0.1.0", ) + go_repository( + name = "com_github_iris_contrib_schema", + importpath = "github.com/iris-contrib/schema", + sum = "h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw=", + version = "v0.0.6", + ) + go_repository( + name = "com_github_joker_jade", + importpath = "github.com/Joker/jade", + sum = "h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk=", + version = "v1.1.3", + ) go_repository( name = "com_github_josharian_intern", importpath = "github.com/josharian/intern", @@ -685,6 +763,42 @@ def go_deps(): sum = "h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=", version = "v1.3.0", ) + go_repository( + name = "com_github_kataras_blocks", + importpath = "github.com/kataras/blocks", + sum = "h1:cF3RDY/vxnSRezc7vLFlQFTYXG/yAr1o7WImJuZbzC4=", + version = "v0.0.7", + ) + go_repository( + name = "com_github_kataras_golog", + importpath = "github.com/kataras/golog", + sum = "h1:vLvSDpP7kihFGKFAvBSofYo7qZNULYSHOH2D7rPTKJk=", + version = "v0.1.9", + ) + go_repository( + name = "com_github_kataras_iris_v12", + importpath = "github.com/kataras/iris/v12", + sum = "h1:R5UzUW4MIByBM6tKMG3UqJ7hL1JCEE+dkqQ8L72f6PU=", + version = "v12.2.5", + ) + go_repository( + name = "com_github_kataras_pio", + importpath = "github.com/kataras/pio", + sum = "h1:o52SfVYauS3J5X08fNjlGS5arXHjW/ItLkyLcKjoH6w=", + version = "v0.0.12", + ) + go_repository( + name = "com_github_kataras_sitemap", + importpath = "github.com/kataras/sitemap", + sum = "h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY=", + version = "v0.0.6", + ) + go_repository( + name = "com_github_kataras_tunnel", + importpath = "github.com/kataras/tunnel", + sum = "h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA=", + version = "v0.0.4", + ) go_repository( name = "com_github_kballard_go_shellquote", importpath = "github.com/kballard/go-shellquote", @@ -706,14 +820,14 @@ def go_deps(): go_repository( name = "com_github_klauspost_compress", importpath = "github.com/klauspost/compress", - sum = "h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=", - version = "v1.15.11", + sum = "h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=", + version = "v1.16.7", ) go_repository( name = "com_github_klauspost_cpuid_v2", importpath = "github.com/klauspost/cpuid/v2", - sum = "h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=", - version = "v2.2.3", + sum = "h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=", + version = "v2.2.5", ) go_repository( name = "com_github_konsorten_go_windows_terminal_sequences", @@ -754,8 +868,8 @@ def go_deps(): go_repository( name = "com_github_labstack_echo_v4", importpath = "github.com/labstack/echo/v4", - sum = "h1:5CiyngihEO4HXsz3vVsJn7f8xAlWwRr3aY6Ih280ZKA=", - version = "v4.10.0", + sum = "h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4=", + version = "v4.11.1", ) go_repository( name = "com_github_labstack_gommon", @@ -766,8 +880,8 @@ def go_deps(): go_repository( name = "com_github_leodido_go_urn", importpath = "github.com/leodido/go-urn", - sum = "h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=", - version = "v1.2.1", + sum = "h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=", + version = "v1.2.4", ) go_repository( name = "com_github_lestrrat_go_backoff_v2", @@ -811,18 +925,18 @@ def go_deps(): sum = "h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=", version = "v1.8.7", ) + go_repository( + name = "com_github_mailgun_raymond_v2", + importpath = "github.com/mailgun/raymond/v2", + sum = "h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=", + version = "v2.0.48", + ) go_repository( name = "com_github_mailru_easyjson", importpath = "github.com/mailru/easyjson", sum = "h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=", version = "v0.7.7", ) - go_repository( - name = "com_github_matryer_moq", - importpath = "github.com/matryer/moq", - sum = "h1:4j0goF/XK3pMTc7fJB3fveuTJoQNdavRX/78vlK3Xb4=", - version = "v0.3.0", - ) go_repository( name = "com_github_mattn_go_colorable", importpath = "github.com/mattn/go-colorable", @@ -832,8 +946,8 @@ def go_deps(): go_repository( name = "com_github_mattn_go_isatty", importpath = "github.com/mattn/go-isatty", - sum = "h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=", - version = "v0.0.17", + sum = "h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=", + version = "v0.0.19", ) go_repository( name = "com_github_mattn_go_runewidth", @@ -853,6 +967,12 @@ def go_deps(): sum = "h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=", version = "v1.0.1", ) + go_repository( + name = "com_github_microcosm_cc_bluemonday", + importpath = "github.com/microcosm-cc/bluemonday", + sum = "h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg=", + version = "v1.0.25", + ) go_repository( name = "com_github_microsoft_go_winio", importpath = "github.com/Microsoft/go-winio", @@ -913,6 +1033,12 @@ def go_deps(): sum = "h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=", version = "v0.0.0-20200227124842-a10e7caefd8e", ) + go_repository( + name = "com_github_oapi_codegen_runtime", + importpath = "github.com/oapi-codegen/runtime", + sum = "h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo=", + version = "v1.0.0", + ) go_repository( name = "com_github_olekukonko_tablewriter", importpath = "github.com/olekukonko/tablewriter", @@ -964,8 +1090,8 @@ def go_deps(): go_repository( name = "com_github_pelletier_go_toml_v2", importpath = "github.com/pelletier/go-toml/v2", - sum = "h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=", - version = "v2.0.6", + sum = "h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=", + version = "v2.0.9", ) go_repository( name = "com_github_perimeterx_marshmallow", @@ -1063,12 +1189,24 @@ def go_deps(): sum = "h1:fipzMFW34hFUEc4D7fsLQFtE7yElkpgyS2zruedRdZk=", version = "v0.9.0", ) + go_repository( + name = "com_github_schollz_closestmatch", + importpath = "github.com/schollz/closestmatch", + sum = "h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk=", + version = "v2.1.0+incompatible", + ) go_repository( name = "com_github_sergi_go_diff", importpath = "github.com/sergi/go-diff", sum = "h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=", version = "v1.3.1", ) + go_repository( + name = "com_github_shopify_goreferrer", + importpath = "github.com/Shopify/goreferrer", + sum = "h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0=", + version = "v0.0.0-20220729165902-8cddb4f5de06", + ) go_repository( name = "com_github_sirupsen_logrus", importpath = "github.com/sirupsen/logrus", @@ -1144,8 +1282,8 @@ def go_deps(): go_repository( name = "com_github_stretchr_testify", importpath = "github.com/stretchr/testify", - sum = "h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=", - version = "v1.8.1", + sum = "h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=", + version = "v1.8.4", ) go_repository( name = "com_github_subosito_gotenv", @@ -1153,6 +1291,24 @@ def go_deps(): sum = "h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=", version = "v1.4.2", ) + go_repository( + name = "com_github_tdewolff_minify_v2", + importpath = "github.com/tdewolff/minify/v2", + sum = "h1:Q2BqOTmlMjoutkuD/OPCnJUpIqrzT3nRPkw+q+KpXS0=", + version = "v2.12.8", + ) + go_repository( + name = "com_github_tdewolff_parse_v2", + importpath = "github.com/tdewolff/parse/v2", + sum = "h1:WrFllrqmzAcrKHzoYgMupqgUBIfBVOb0yscFzDf8bBg=", + version = "v2.6.7", + ) + go_repository( + name = "com_github_twitchyliquid64_golang_asm", + importpath = "github.com/twitchyliquid64/golang-asm", + sum = "h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=", + version = "v0.15.1", + ) go_repository( name = "com_github_uber_jaeger_client_go", importpath = "github.com/uber/jaeger-client-go", @@ -1174,8 +1330,8 @@ def go_deps(): go_repository( name = "com_github_ugorji_go_codec", importpath = "github.com/ugorji/go/codec", - sum = "h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=", - version = "v1.2.7", + sum = "h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=", + version = "v1.2.11", ) go_repository( name = "com_github_valyala_bytebufferpool", @@ -1207,6 +1363,24 @@ def go_deps(): sum = "h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=", version = "v0.0.0-20200728191858-db3c7e526aae", ) + go_repository( + name = "com_github_vmihailenco_msgpack_v5", + importpath = "github.com/vmihailenco/msgpack/v5", + sum = "h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=", + version = "v5.3.5", + ) + go_repository( + name = "com_github_vmihailenco_tagparser_v2", + importpath = "github.com/vmihailenco/tagparser/v2", + sum = "h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=", + version = "v2.0.0", + ) + go_repository( + name = "com_github_yosssi_ace", + importpath = "github.com/yosssi/ace", + sum = "h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=", + version = "v0.0.5", + ) go_repository( name = "com_github_yuin_goldmark", importpath = "github.com/yuin/goldmark", @@ -1425,11 +1599,17 @@ def go_deps(): sum = "h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=", version = "v1.31.0", ) + go_repository( + name = "org_golang_x_arch", + importpath = "golang.org/x/arch", + sum = "h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=", + version = "v0.4.0", + ) go_repository( name = "org_golang_x_crypto", importpath = "golang.org/x/crypto", - sum = "h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=", - version = "v0.6.0", + sum = "h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=", + version = "v0.12.0", ) go_repository( name = "org_golang_x_exp", @@ -1452,8 +1632,8 @@ def go_deps(): go_repository( name = "org_golang_x_lint", importpath = "golang.org/x/lint", - sum = "h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=", - version = "v0.0.0-20201208152925-83fdc39ff7b5", + sum = "h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=", + version = "v0.0.0-20210508222113-6edffad5e616", ) go_repository( name = "org_golang_x_mobile", @@ -1464,14 +1644,14 @@ def go_deps(): go_repository( name = "org_golang_x_mod", importpath = "golang.org/x/mod", - sum = "h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=", - version = "v0.11.0", + sum = "h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=", + version = "v0.12.0", ) go_repository( name = "org_golang_x_net", importpath = "golang.org/x/net", - sum = "h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=", - version = "v0.10.0", + sum = "h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=", + version = "v0.14.0", ) go_repository( name = "org_golang_x_oauth2", @@ -1494,26 +1674,26 @@ def go_deps(): go_repository( name = "org_golang_x_term", importpath = "golang.org/x/term", - sum = "h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=", - version = "v0.8.0", + sum = "h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=", + version = "v0.11.0", ) go_repository( name = "org_golang_x_text", importpath = "golang.org/x/text", - sum = "h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=", - version = "v0.9.0", + sum = "h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=", + version = "v0.13.0", ) go_repository( name = "org_golang_x_time", importpath = "golang.org/x/time", - sum = "h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=", - version = "v0.2.0", + sum = "h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=", + version = "v0.3.0", ) go_repository( name = "org_golang_x_tools", importpath = "golang.org/x/tools", - sum = "h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=", - version = "v0.9.1", + sum = "h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=", + version = "v0.12.0", ) go_repository( name = "org_golang_x_xerrors", diff --git a/licenses/data/com_github_deepmap_oapi_codegen/LICENSE b/licenses/data/com_github_deepmap_oapi_codegen_v2/LICENSE similarity index 100% rename from licenses/data/com_github_deepmap_oapi_codegen/LICENSE rename to licenses/data/com_github_deepmap_oapi_codegen_v2/LICENSE diff --git a/licenses/data/com_github_labstack_echo_v4/LICENSE b/licenses/data/com_github_labstack_echo_v4/LICENSE deleted file mode 100644 index c46d0105f..000000000 --- a/licenses/data/com_github_labstack_echo_v4/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2021 LabStack - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/licenses/data/com_github_labstack_gommon/LICENSE b/licenses/data/com_github_labstack_gommon/LICENSE deleted file mode 100644 index fc718faf2..000000000 --- a/licenses/data/com_github_labstack_gommon/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2018 labstack - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/licenses/data/com_github_oapi_codegen_runtime/LICENSE b/licenses/data/com_github_oapi_codegen_runtime/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/licenses/data/com_github_oapi_codegen_runtime/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/licenses/data/com_github_valyala_bytebufferpool/LICENSE b/licenses/data/com_github_valyala_bytebufferpool/LICENSE deleted file mode 100644 index f7c935c20..000000000 --- a/licenses/data/com_github_valyala_bytebufferpool/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Aliaksandr Valialkin, VertaMedia - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/licenses/data/com_github_valyala_fasttemplate/LICENSE b/licenses/data/com_github_valyala_fasttemplate/LICENSE deleted file mode 100644 index 7125a63c4..000000000 --- a/licenses/data/com_github_valyala_fasttemplate/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Aliaksandr Valialkin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/nogo.json b/nogo.json index 924de87ac..d3ada1568 100644 --- a/nogo.json +++ b/nogo.json @@ -2,7 +2,6 @@ "assign": { "exclude_files": { "gazelle/walk/walk.go": "", - "com_github_deepmap_oapi_codegen/pkg/codegen/": "", "/org_modernc_sqlite": "" } }, @@ -149,7 +148,7 @@ }, "maincheck": { "exclude_files": { - "/com_github_deepmap_oapi_codegen/": "", + "/com_github_deepmap_oapi_codegen_v2/": "", "/com_github_golang_mock/mockgen": "", "/org_golang_x_tools": "", "gazelle/language/go/gen_std_package_list": "", @@ -184,7 +183,6 @@ "com_github_matttproud_golang_protobuf_extensions": "", "com_github_getkin_kin_openapi": "", "com_github_buildkite_go_buildkite_v2/buildkite": "", - "com_github_deepmap_oapi_codegen/pkg/runtime": "", "com_github_uber_jaeger_client_go/thrift": "", "com_github_hashicorp_hcl": "", "com_github_stretchr_testify/assert": "", @@ -199,7 +197,6 @@ "com_github_uber_jaeger_client_go": "", "com_github_spf13_viper": "", "com_github_labstack_echo_v4": "", - "com_github_deepmap_oapi_codegen": "", "pkg/private/serrors/errors.go": "err shadowed", "pkg/slayers/path/scion/raw.go": "err shadowed", "pkg/scrypto/cppki/trc.go": "err shadowed", @@ -212,7 +209,7 @@ "org_golang_x_mod": "", "org_golang_x_crypto/ed25519/internal/edwards25519": "", "com_github_vishvananda_netlink/nl": "", - "com_github_deepmap_oapi_codegen/pkg/codegen": "", + "com_github_deepmap_oapi_codegen_v2/pkg/codegen": "", "com_github_quic_go_quic_go": "", "com_github_bazelbuild_buildtools": "", "/bazel_gazelle/": "" diff --git a/private/ca/api/BUILD.bazel b/private/ca/api/BUILD.bazel index 2d1759546..bd175b3d8 100644 --- a/private/ca/api/BUILD.bazel +++ b/private/ca/api/BUILD.bazel @@ -19,7 +19,7 @@ go_library( importpath = "github.com/scionproto/scion/private/ca/api", visibility = ["//visibility:public"], deps = [ - "@com_github_deepmap_oapi_codegen//pkg/runtime:go_default_library", # keep - "@com_github_deepmap_oapi_codegen//pkg/types:go_default_library", # keep + "@com_github_oapi_codegen_runtime//:go_default_library", # keep + "@com_github_oapi_codegen_runtime//types:go_default_library", # keep ], ) diff --git a/private/ca/api/client.gen.go b/private/ca/api/client.gen.go index e32c482e3..bf2faefae 100644 --- a/private/ca/api/client.gen.go +++ b/private/ca/api/client.gen.go @@ -13,7 +13,7 @@ import ( "net/url" "strings" - "github.com/deepmap/oapi-codegen/pkg/runtime" + "github.com/oapi-codegen/runtime" ) // RequestEditorFn is the function signature for the RequestEditor callback function @@ -89,7 +89,7 @@ func WithRequestEditorFn(fn RequestEditorFn) ClientOption { // The interface specification for the client above. type ClientInterface interface { - // PostAuthToken request with any body + // PostAuthTokenWithBody request with any body PostAuthTokenWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) PostAuthToken(ctx context.Context, body PostAuthTokenJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -97,7 +97,7 @@ type ClientInterface interface { // GetHealthcheck request GetHealthcheck(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - // PostCertificateRenewal request with any body + // PostCertificateRenewalWithBody request with any body PostCertificateRenewalWithBody(ctx context.Context, isdNumber int, asNumber AS, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) PostCertificateRenewal(ctx context.Context, isdNumber int, asNumber AS, body PostCertificateRenewalJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -327,28 +327,28 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // PostAuthToken request with any body + // PostAuthTokenWithBodyWithResponse request with any body PostAuthTokenWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostAuthTokenResponse, error) PostAuthTokenWithResponse(ctx context.Context, body PostAuthTokenJSONRequestBody, reqEditors ...RequestEditorFn) (*PostAuthTokenResponse, error) - // GetHealthcheck request + // GetHealthcheckWithResponse request GetHealthcheckWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetHealthcheckResponse, error) - // PostCertificateRenewal request with any body + // PostCertificateRenewalWithBodyWithResponse request with any body PostCertificateRenewalWithBodyWithResponse(ctx context.Context, isdNumber int, asNumber AS, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostCertificateRenewalResponse, error) PostCertificateRenewalWithResponse(ctx context.Context, isdNumber int, asNumber AS, body PostCertificateRenewalJSONRequestBody, reqEditors ...RequestEditorFn) (*PostCertificateRenewalResponse, error) } type PostAuthTokenResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AccessToken - JSON400 *Problem - JSON401 *Problem - JSON500 *Problem - JSON503 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *AccessToken + ApplicationproblemJSON400 *N400BadRequest + ApplicationproblemJSON401 *N401UnauthorizedError + ApplicationproblemJSON500 *N500InternalServerError + ApplicationproblemJSON503 *N503ServiceUnavailable } // Status returns HTTPResponse.Status @@ -368,11 +368,11 @@ func (r PostAuthTokenResponse) StatusCode() int { } type GetHealthcheckResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *HealthCheckStatus - JSON500 *Problem - JSON503 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *HealthCheckStatus + ApplicationproblemJSON500 *N500InternalServerError + ApplicationproblemJSON503 *N503ServiceUnavailable } // Status returns HTTPResponse.Status @@ -392,14 +392,14 @@ func (r GetHealthcheckResponse) StatusCode() int { } type PostCertificateRenewalResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *RenewalResponse - JSON400 *Problem - JSON401 *Problem - JSON404 *Problem - JSON500 *Problem - JSON503 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *RenewalResponse + ApplicationproblemJSON400 *N400BadRequest + ApplicationproblemJSON401 *N401UnauthorizedError + ApplicationproblemJSON404 *N404NotFound + ApplicationproblemJSON500 *N500InternalServerError + ApplicationproblemJSON503 *N503ServiceUnavailable } // Status returns HTTPResponse.Status @@ -483,32 +483,32 @@ func ParsePostAuthTokenResponse(rsp *http.Response) (*PostAuthTokenResponse, err response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest Problem + var dest N400BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest Problem + var dest N401UnauthorizedError if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON401 = &dest + response.ApplicationproblemJSON401 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest Problem + var dest N500InternalServerError if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON500 = &dest + response.ApplicationproblemJSON500 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 503: - var dest Problem + var dest N503ServiceUnavailable if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON503 = &dest + response.ApplicationproblemJSON503 = &dest } @@ -537,18 +537,18 @@ func ParseGetHealthcheckResponse(rsp *http.Response) (*GetHealthcheckResponse, e response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest Problem + var dest N500InternalServerError if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON500 = &dest + response.ApplicationproblemJSON500 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 503: - var dest Problem + var dest N503ServiceUnavailable if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON503 = &dest + response.ApplicationproblemJSON503 = &dest } @@ -577,39 +577,39 @@ func ParsePostCertificateRenewalResponse(rsp *http.Response) (*PostCertificateRe response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest Problem + var dest N400BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest Problem + var dest N401UnauthorizedError if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON401 = &dest + response.ApplicationproblemJSON401 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest Problem + var dest N404NotFound if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON404 = &dest + response.ApplicationproblemJSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest Problem + var dest N500InternalServerError if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON500 = &dest + response.ApplicationproblemJSON500 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 503: - var dest Problem + var dest N503ServiceUnavailable if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON503 = &dest + response.ApplicationproblemJSON503 = &dest } diff --git a/private/ca/api/types.gen.go b/private/ca/api/types.gen.go index db9693896..f438c1a3a 100644 --- a/private/ca/api/types.gen.go +++ b/private/ca/api/types.gen.go @@ -6,8 +6,8 @@ package api import ( "encoding/json" - "github.com/deepmap/oapi-codegen/pkg/runtime" - openapi_types "github.com/deepmap/oapi-codegen/pkg/types" + "github.com/oapi-codegen/runtime" + openapi_types "github.com/oapi-codegen/runtime/types" ) const ( @@ -133,6 +133,26 @@ type RenewalResponse_CertificateChain struct { union json.RawMessage } +// N400BadRequest Error message encoded as specified in +// [RFC7807](https://tools.ietf.org/html/rfc7807) +type N400BadRequest = Problem + +// N401UnauthorizedError Error message encoded as specified in +// [RFC7807](https://tools.ietf.org/html/rfc7807) +type N401UnauthorizedError = Problem + +// N404NotFound Error message encoded as specified in +// [RFC7807](https://tools.ietf.org/html/rfc7807) +type N404NotFound = Problem + +// N500InternalServerError Error message encoded as specified in +// [RFC7807](https://tools.ietf.org/html/rfc7807) +type N500InternalServerError = Problem + +// N503ServiceUnavailable Error message encoded as specified in +// [RFC7807](https://tools.ietf.org/html/rfc7807) +type N503ServiceUnavailable = Problem + // PostAuthTokenJSONRequestBody defines body for PostAuthToken for application/json ContentType. type PostAuthTokenJSONRequestBody = AccessCredentials @@ -160,7 +180,7 @@ func (t *RenewalResponse_CertificateChain) MergeCertificateChain(v CertificateCh return err } - merged, err := runtime.JsonMerge(b, t.union) + merged, err := runtime.JsonMerge(t.union, b) t.union = merged return err } @@ -186,7 +206,7 @@ func (t *RenewalResponse_CertificateChain) MergeCertificateChainPKCS7(v Certific return err } - merged, err := runtime.JsonMerge(b, t.union) + merged, err := runtime.JsonMerge(t.union, b) t.union = merged return err } diff --git a/private/mgmtapi/cppki/api/BUILD.bazel b/private/mgmtapi/cppki/api/BUILD.bazel index 8e0d5d1f3..aecf1229a 100644 --- a/private/mgmtapi/cppki/api/BUILD.bazel +++ b/private/mgmtapi/cppki/api/BUILD.bazel @@ -26,8 +26,8 @@ go_library( "//private/storage:go_default_library", "//private/storage/trust:go_default_library", "//private/trust:go_default_library", - "@com_github_deepmap_oapi_codegen//pkg/runtime:go_default_library", # keep "@com_github_go_chi_chi_v5//:go_default_library", # keep + "@com_github_oapi_codegen_runtime//:go_default_library", # keep ], ) diff --git a/private/mgmtapi/cppki/api/client.gen.go b/private/mgmtapi/cppki/api/client.gen.go index 01dc6bb5f..d47e1534e 100644 --- a/private/mgmtapi/cppki/api/client.gen.go +++ b/private/mgmtapi/cppki/api/client.gen.go @@ -12,7 +12,7 @@ import ( "net/url" "strings" - "github.com/deepmap/oapi-codegen/pkg/runtime" + "github.com/oapi-codegen/runtime" ) // RequestEditorFn is the function signature for the RequestEditor callback function @@ -198,58 +198,60 @@ func NewGetCertificatesRequest(server string, params *GetCertificatesParams) (*h return nil, err } - queryValues := queryURL.Query() + if params != nil { + queryValues := queryURL.Query() - if params.IsdAs != nil { + if params.IsdAs != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "isd_as", runtime.ParamLocationQuery, *params.IsdAs); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "isd_as", runtime.ParamLocationQuery, *params.IsdAs); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - } - - if params.ValidAt != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "valid_at", runtime.ParamLocationQuery, *params.ValidAt); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.ValidAt != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "valid_at", runtime.ParamLocationQuery, *params.ValidAt); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - - } - if params.All != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.All != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } + } + queryURL.RawQuery = queryValues.Encode() } - queryURL.RawQuery = queryValues.Encode() - req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -345,42 +347,44 @@ func NewGetTrcsRequest(server string, params *GetTrcsParams) (*http.Request, err return nil, err } - queryValues := queryURL.Query() + if params != nil { + queryValues := queryURL.Query() - if params.Isd != nil { + if params.Isd != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "isd", runtime.ParamLocationQuery, *params.Isd); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "isd", runtime.ParamLocationQuery, *params.Isd); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - - } - if params.All != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.All != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "all", runtime.ParamLocationQuery, *params.All); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } + } + queryURL.RawQuery = queryValues.Encode() } - queryURL.RawQuery = queryValues.Encode() - req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -528,30 +532,30 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // GetCertificates request + // GetCertificatesWithResponse request GetCertificatesWithResponse(ctx context.Context, params *GetCertificatesParams, reqEditors ...RequestEditorFn) (*GetCertificatesResponse, error) - // GetCertificate request + // GetCertificateWithResponse request GetCertificateWithResponse(ctx context.Context, chainId ChainID, reqEditors ...RequestEditorFn) (*GetCertificateResponse, error) - // GetCertificateBlob request + // GetCertificateBlobWithResponse request GetCertificateBlobWithResponse(ctx context.Context, chainId ChainID, reqEditors ...RequestEditorFn) (*GetCertificateBlobResponse, error) - // GetTrcs request + // GetTrcsWithResponse request GetTrcsWithResponse(ctx context.Context, params *GetTrcsParams, reqEditors ...RequestEditorFn) (*GetTrcsResponse, error) - // GetTrc request + // GetTrcWithResponse request GetTrcWithResponse(ctx context.Context, isd int, base int, serial int, reqEditors ...RequestEditorFn) (*GetTrcResponse, error) - // GetTrcBlob request + // GetTrcBlobWithResponse request GetTrcBlobWithResponse(ctx context.Context, isd int, base int, serial int, reqEditors ...RequestEditorFn) (*GetTrcBlobResponse, error) } type GetCertificatesResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *[]ChainBrief - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *[]ChainBrief + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -571,10 +575,10 @@ func (r GetCertificatesResponse) StatusCode() int { } type GetCertificateResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *Chain - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *Chain + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -594,9 +598,9 @@ func (r GetCertificateResponse) StatusCode() int { } type GetCertificateBlobResponse struct { - Body []byte - HTTPResponse *http.Response - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -619,7 +623,7 @@ type GetTrcsResponse struct { Body []byte HTTPResponse *http.Response JSON200 *[]TRCBrief - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -642,7 +646,7 @@ type GetTrcResponse struct { Body []byte HTTPResponse *http.Response JSON200 *TRC - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -664,7 +668,7 @@ func (r GetTrcResponse) StatusCode() int { type GetTrcBlobResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -763,7 +767,7 @@ func ParseGetCertificatesResponse(rsp *http.Response) (*GetCertificatesResponse, if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -796,7 +800,7 @@ func ParseGetCertificateResponse(rsp *http.Response) (*GetCertificateResponse, e if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -822,7 +826,7 @@ func ParseGetCertificateBlobResponse(rsp *http.Response) (*GetCertificateBlobRes if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -851,7 +855,7 @@ func ParseGetTrcsResponse(rsp *http.Response) (*GetTrcsResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -884,7 +888,7 @@ func ParseGetTrcResponse(rsp *http.Response) (*GetTrcResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -910,7 +914,7 @@ func ParseGetTrcBlobResponse(rsp *http.Response) (*GetTrcBlobResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/private/mgmtapi/cppki/api/server.gen.go b/private/mgmtapi/cppki/api/server.gen.go index 55f02bc0e..9ba0ad5b4 100644 --- a/private/mgmtapi/cppki/api/server.gen.go +++ b/private/mgmtapi/cppki/api/server.gen.go @@ -7,8 +7,8 @@ import ( "fmt" "net/http" - "github.com/deepmap/oapi-codegen/pkg/runtime" "github.com/go-chi/chi/v5" + "github.com/oapi-codegen/runtime" ) // ServerInterface represents all server handlers. @@ -33,6 +33,46 @@ type ServerInterface interface { GetTrcBlob(w http.ResponseWriter, r *http.Request, isd int, base int, serial int) } +// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint. + +type Unimplemented struct{} + +// List the certificate chains +// (GET /certificates) +func (_ Unimplemented) GetCertificates(w http.ResponseWriter, r *http.Request, params GetCertificatesParams) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the certificate chain +// (GET /certificates/{chain-id}) +func (_ Unimplemented) GetCertificate(w http.ResponseWriter, r *http.Request, chainId ChainID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the certificate chain blob +// (GET /certificates/{chain-id}/blob) +func (_ Unimplemented) GetCertificateBlob(w http.ResponseWriter, r *http.Request, chainId ChainID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// List the TRCs +// (GET /trcs) +func (_ Unimplemented) GetTrcs(w http.ResponseWriter, r *http.Request, params GetTrcsParams) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the TRC +// (GET /trcs/isd{isd}-b{base}-s{serial}) +func (_ Unimplemented) GetTrc(w http.ResponseWriter, r *http.Request, isd int, base int, serial int) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the TRC blob +// (GET /trcs/isd{isd}-b{base}-s{serial}/blob) +func (_ Unimplemented) GetTrcBlob(w http.ResponseWriter, r *http.Request, isd int, base int, serial int) { + w.WriteHeader(http.StatusNotImplemented) +} + // ServerInterfaceWrapper converts contexts to parameters. type ServerInterfaceWrapper struct { Handler ServerInterface @@ -75,9 +115,9 @@ func (siw *ServerInterfaceWrapper) GetCertificates(w http.ResponseWriter, r *htt return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificates(w, r, params) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -101,9 +141,9 @@ func (siw *ServerInterfaceWrapper) GetCertificate(w http.ResponseWriter, r *http return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificate(w, r, chainId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -127,9 +167,9 @@ func (siw *ServerInterfaceWrapper) GetCertificateBlob(w http.ResponseWriter, r * return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetCertificateBlob(w, r, chainId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -163,9 +203,9 @@ func (siw *ServerInterfaceWrapper) GetTrcs(w http.ResponseWriter, r *http.Reques return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcs(w, r, params) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -207,9 +247,9 @@ func (siw *ServerInterfaceWrapper) GetTrc(w http.ResponseWriter, r *http.Request return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrc(w, r, isd, base, serial) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -251,9 +291,9 @@ func (siw *ServerInterfaceWrapper) GetTrcBlob(w http.ResponseWriter, r *http.Req return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetTrcBlob(w, r, isd, base, serial) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -275,16 +315,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshallingParamError struct { +type UnmarshalingParamError struct { ParamName string Err error } -func (e *UnmarshallingParamError) Error() string { - return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshalingParamError) Error() string { + return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshallingParamError) Unwrap() error { +func (e *UnmarshalingParamError) Unwrap() error { return e.Err } diff --git a/private/mgmtapi/health/api/client.gen.go b/private/mgmtapi/health/api/client.gen.go index d4df7b2bc..4f1f990cd 100644 --- a/private/mgmtapi/health/api/client.gen.go +++ b/private/mgmtapi/health/api/client.gen.go @@ -172,7 +172,7 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // GetHealth request + // GetHealthWithResponse request GetHealthWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetHealthResponse, error) } @@ -180,7 +180,7 @@ type GetHealthResponse struct { Body []byte HTTPResponse *http.Response JSON200 *HealthResponse - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -230,7 +230,7 @@ func ParseGetHealthResponse(rsp *http.Response) (*GetHealthResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/private/mgmtapi/health/api/server.gen.go b/private/mgmtapi/health/api/server.gen.go index f21264e57..97abd0b6b 100644 --- a/private/mgmtapi/health/api/server.gen.go +++ b/private/mgmtapi/health/api/server.gen.go @@ -17,6 +17,16 @@ type ServerInterface interface { GetHealth(w http.ResponseWriter, r *http.Request) } +// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint. + +type Unimplemented struct{} + +// Indicate the service health. +// (GET /health) +func (_ Unimplemented) GetHealth(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + // ServerInterfaceWrapper converts contexts to parameters. type ServerInterfaceWrapper struct { Handler ServerInterface @@ -30,9 +40,9 @@ type MiddlewareFunc func(http.Handler) http.Handler func (siw *ServerInterfaceWrapper) GetHealth(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetHealth(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -54,16 +64,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshallingParamError struct { +type UnmarshalingParamError struct { ParamName string Err error } -func (e *UnmarshallingParamError) Error() string { - return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshalingParamError) Error() string { + return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshallingParamError) Unwrap() error { +func (e *UnmarshalingParamError) Unwrap() error { return e.Err } diff --git a/private/mgmtapi/segments/api/BUILD.bazel b/private/mgmtapi/segments/api/BUILD.bazel index ef2a43e8d..c7370ad4c 100644 --- a/private/mgmtapi/segments/api/BUILD.bazel +++ b/private/mgmtapi/segments/api/BUILD.bazel @@ -23,8 +23,8 @@ go_library( "//pkg/segment:go_default_library", "//private/mgmtapi:go_default_library", "//private/pathdb/query:go_default_library", - "@com_github_deepmap_oapi_codegen//pkg/runtime:go_default_library", # keep "@com_github_go_chi_chi_v5//:go_default_library", # keep + "@com_github_oapi_codegen_runtime//:go_default_library", # keep "@org_golang_google_protobuf//proto:go_default_library", ], ) diff --git a/private/mgmtapi/segments/api/client.gen.go b/private/mgmtapi/segments/api/client.gen.go index b0f6e2ca3..795cdc14a 100644 --- a/private/mgmtapi/segments/api/client.gen.go +++ b/private/mgmtapi/segments/api/client.gen.go @@ -12,7 +12,7 @@ import ( "net/url" "strings" - "github.com/deepmap/oapi-codegen/pkg/runtime" + "github.com/oapi-codegen/runtime" ) // RequestEditorFn is the function signature for the RequestEditor callback function @@ -153,42 +153,44 @@ func NewGetSegmentsRequest(server string, params *GetSegmentsParams) (*http.Requ return nil, err } - queryValues := queryURL.Query() + if params != nil { + queryValues := queryURL.Query() - if params.StartIsdAs != nil { + if params.StartIsdAs != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "start_isd_as", runtime.ParamLocationQuery, *params.StartIsdAs); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "start_isd_as", runtime.ParamLocationQuery, *params.StartIsdAs); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } - } - } - - if params.EndIsdAs != nil { + } - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "end_isd_as", runtime.ParamLocationQuery, *params.EndIsdAs); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) + if params.EndIsdAs != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "end_isd_as", runtime.ParamLocationQuery, *params.EndIsdAs); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } } } + } + queryURL.RawQuery = queryValues.Encode() } - queryURL.RawQuery = queryValues.Encode() - req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -308,21 +310,21 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // GetSegments request + // GetSegmentsWithResponse request GetSegmentsWithResponse(ctx context.Context, params *GetSegmentsParams, reqEditors ...RequestEditorFn) (*GetSegmentsResponse, error) - // GetSegment request + // GetSegmentWithResponse request GetSegmentWithResponse(ctx context.Context, segmentId SegmentID, reqEditors ...RequestEditorFn) (*GetSegmentResponse, error) - // GetSegmentBlob request + // GetSegmentBlobWithResponse request GetSegmentBlobWithResponse(ctx context.Context, segmentId SegmentID, reqEditors ...RequestEditorFn) (*GetSegmentBlobResponse, error) } type GetSegmentsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *[]SegmentBrief - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *[]SegmentBrief + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -342,10 +344,10 @@ func (r GetSegmentsResponse) StatusCode() int { } type GetSegmentResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *Segment - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *Segment + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -365,9 +367,9 @@ func (r GetSegmentResponse) StatusCode() int { } type GetSegmentBlobResponse struct { - Body []byte - HTTPResponse *http.Response - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -439,7 +441,7 @@ func ParseGetSegmentsResponse(rsp *http.Response) (*GetSegmentsResponse, error) if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -472,7 +474,7 @@ func ParseGetSegmentResponse(rsp *http.Response) (*GetSegmentResponse, error) { if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -498,7 +500,7 @@ func ParseGetSegmentBlobResponse(rsp *http.Response) (*GetSegmentBlobResponse, e if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } diff --git a/private/mgmtapi/segments/api/server.gen.go b/private/mgmtapi/segments/api/server.gen.go index b27cd475d..28cffab75 100644 --- a/private/mgmtapi/segments/api/server.gen.go +++ b/private/mgmtapi/segments/api/server.gen.go @@ -7,8 +7,8 @@ import ( "fmt" "net/http" - "github.com/deepmap/oapi-codegen/pkg/runtime" "github.com/go-chi/chi/v5" + "github.com/oapi-codegen/runtime" ) // ServerInterface represents all server handlers. @@ -24,6 +24,28 @@ type ServerInterface interface { GetSegmentBlob(w http.ResponseWriter, r *http.Request, segmentId SegmentID) } +// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint. + +type Unimplemented struct{} + +// List the SCION path segments +// (GET /segments) +func (_ Unimplemented) GetSegments(w http.ResponseWriter, r *http.Request, params GetSegmentsParams) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the SCION path segment description +// (GET /segments/{segment-id}) +func (_ Unimplemented) GetSegment(w http.ResponseWriter, r *http.Request, segmentId SegmentID) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get the SCION path segment blob +// (GET /segments/{segment-id}/blob) +func (_ Unimplemented) GetSegmentBlob(w http.ResponseWriter, r *http.Request, segmentId SegmentID) { + w.WriteHeader(http.StatusNotImplemented) +} + // ServerInterfaceWrapper converts contexts to parameters. type ServerInterfaceWrapper struct { Handler ServerInterface @@ -58,9 +80,9 @@ func (siw *ServerInterfaceWrapper) GetSegments(w http.ResponseWriter, r *http.Re return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegments(w, r, params) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -84,9 +106,9 @@ func (siw *ServerInterfaceWrapper) GetSegment(w http.ResponseWriter, r *http.Req return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegment(w, r, segmentId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -110,9 +132,9 @@ func (siw *ServerInterfaceWrapper) GetSegmentBlob(w http.ResponseWriter, r *http return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetSegmentBlob(w, r, segmentId) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -134,16 +156,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshallingParamError struct { +type UnmarshalingParamError struct { ParamName string Err error } -func (e *UnmarshallingParamError) Error() string { - return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshalingParamError) Error() string { + return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshallingParamError) Unwrap() error { +func (e *UnmarshalingParamError) Unwrap() error { return e.Err } diff --git a/router/mgmtapi/BUILD.bazel b/router/mgmtapi/BUILD.bazel index 887c65731..9d5f48759 100644 --- a/router/mgmtapi/BUILD.bazel +++ b/router/mgmtapi/BUILD.bazel @@ -32,10 +32,9 @@ go_library( "//pkg/addr:go_default_library", "//private/mgmtapi:go_default_library", "//router/control:go_default_library", - "@com_github_deepmap_oapi_codegen//pkg/runtime:go_default_library", # keep "@com_github_getkin_kin_openapi//openapi3:go_default_library", # keep "@com_github_go_chi_chi_v5//:go_default_library", # keep - "@com_github_pkg_errors//:go_default_library", # keep + "@com_github_oapi_codegen_runtime//:go_default_library", # keep ], ) diff --git a/router/mgmtapi/client.gen.go b/router/mgmtapi/client.gen.go index a9f43f310..c6c6c0fb4 100644 --- a/router/mgmtapi/client.gen.go +++ b/router/mgmtapi/client.gen.go @@ -99,7 +99,7 @@ type ClientInterface interface { // GetLogLevel request GetLogLevel(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - // SetLogLevel request with any body + // SetLogLevelWithBody request with any body SetLogLevelWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) SetLogLevel(ctx context.Context, body SetLogLevelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -368,19 +368,19 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // GetConfig request + // GetConfigWithResponse request GetConfigWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetConfigResponse, error) - // GetInfo request + // GetInfoWithResponse request GetInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetInfoResponse, error) - // GetInterfaces request + // GetInterfacesWithResponse request GetInterfacesWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetInterfacesResponse, error) - // GetLogLevel request + // GetLogLevelWithResponse request GetLogLevelWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetLogLevelResponse, error) - // SetLogLevel request with any body + // SetLogLevelWithBodyWithResponse request with any body SetLogLevelWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetLogLevelResponse, error) SetLogLevelWithResponse(ctx context.Context, body SetLogLevelJSONRequestBody, reqEditors ...RequestEditorFn) (*SetLogLevelResponse, error) @@ -389,7 +389,7 @@ type ClientWithResponsesInterface interface { type GetConfigResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -411,7 +411,7 @@ func (r GetConfigResponse) StatusCode() int { type GetInfoResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -431,10 +431,10 @@ func (r GetInfoResponse) StatusCode() int { } type GetInterfacesResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *InterfacesResponse - JSON400 *Problem + Body []byte + HTTPResponse *http.Response + JSON200 *InterfacesResponse + ApplicationproblemJSON400 *Problem } // Status returns HTTPResponse.Status @@ -457,7 +457,7 @@ type GetLogLevelResponse struct { Body []byte HTTPResponse *http.Response JSON200 *LogLevel - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -480,7 +480,7 @@ type SetLogLevelResponse struct { Body []byte HTTPResponse *http.Response JSON200 *LogLevel - JSON400 *StandardError + JSON400 *BadRequest } // Status returns HTTPResponse.Status @@ -567,7 +567,7 @@ func ParseGetConfigResponse(rsp *http.Response) (*GetConfigResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -593,7 +593,7 @@ func ParseGetInfoResponse(rsp *http.Response) (*GetInfoResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -630,7 +630,7 @@ func ParseGetInterfacesResponse(rsp *http.Response) (*GetInterfacesResponse, err if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON400 = &dest + response.ApplicationproblemJSON400 = &dest } @@ -659,7 +659,7 @@ func ParseGetLogLevelResponse(rsp *http.Response) (*GetLogLevelResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -692,7 +692,7 @@ func ParseSetLogLevelResponse(rsp *http.Response) (*SetLogLevelResponse, error) response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest StandardError + var dest BadRequest if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/router/mgmtapi/server.gen.go b/router/mgmtapi/server.gen.go index 0743b7dac..cc1aa483a 100644 --- a/router/mgmtapi/server.gen.go +++ b/router/mgmtapi/server.gen.go @@ -29,6 +29,40 @@ type ServerInterface interface { SetLogLevel(w http.ResponseWriter, r *http.Request) } +// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint. + +type Unimplemented struct{} + +// Prints the TOML configuration file. +// (GET /config) +func (_ Unimplemented) GetConfig(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Basic information page about the control service process. +// (GET /info) +func (_ Unimplemented) GetInfo(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// List the SCION interfaces +// (GET /interfaces) +func (_ Unimplemented) GetInterfaces(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Get logging level +// (GET /log/level) +func (_ Unimplemented) GetLogLevel(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// Set logging level +// (PUT /log/level) +func (_ Unimplemented) SetLogLevel(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + // ServerInterfaceWrapper converts contexts to parameters. type ServerInterfaceWrapper struct { Handler ServerInterface @@ -42,9 +76,9 @@ type MiddlewareFunc func(http.Handler) http.Handler func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetConfig(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -57,9 +91,9 @@ func (siw *ServerInterfaceWrapper) GetConfig(w http.ResponseWriter, r *http.Requ func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInfo(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -72,9 +106,9 @@ func (siw *ServerInterfaceWrapper) GetInfo(w http.ResponseWriter, r *http.Reques func (siw *ServerInterfaceWrapper) GetInterfaces(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetInterfaces(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -87,9 +121,9 @@ func (siw *ServerInterfaceWrapper) GetInterfaces(w http.ResponseWriter, r *http. func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.GetLogLevel(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -102,9 +136,9 @@ func (siw *ServerInterfaceWrapper) GetLogLevel(w http.ResponseWriter, r *http.Re func (siw *ServerInterfaceWrapper) SetLogLevel(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetLogLevel(w, r) - }) + })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) @@ -126,16 +160,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshallingParamError struct { +type UnmarshalingParamError struct { ParamName string Err error } -func (e *UnmarshallingParamError) Error() string { - return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshalingParamError) Error() string { + return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshallingParamError) Unwrap() error { +func (e *UnmarshalingParamError) Unwrap() error { return e.Err } diff --git a/router/mgmtapi/spec.gen.go b/router/mgmtapi/spec.gen.go index b292ce8fb..a344f75ee 100644 --- a/router/mgmtapi/spec.gen.go +++ b/router/mgmtapi/spec.gen.go @@ -64,16 +64,16 @@ var swaggerSpec = []string{ func decodeSpec() ([]byte, error) { zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) if err != nil { - return nil, fmt.Errorf("error base64 decoding spec: %s", err) + return nil, fmt.Errorf("error base64 decoding spec: %w", err) } zr, err := gzip.NewReader(bytes.NewReader(zipped)) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %s", err) + return nil, fmt.Errorf("error decompressing spec: %w", err) } var buf bytes.Buffer _, err = buf.ReadFrom(zr) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %s", err) + return nil, fmt.Errorf("error decompressing spec: %w", err) } return buf.Bytes(), nil @@ -91,7 +91,7 @@ func decodeSpecCached() func() ([]byte, error) { // Constructs a synthetic filesystem for resolving external references when loading openapi specifications. func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { - var res = make(map[string]func() ([]byte, error)) + res := make(map[string]func() ([]byte, error)) if len(pathToFile) > 0 { res[pathToFile] = rawSpec } @@ -105,12 +105,12 @@ func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { // Externally referenced files must be embedded in the corresponding golang packages. // Urls can be supported but this task was out of the scope. func GetSwagger() (swagger *openapi3.T, err error) { - var resolvePath = PathToRawSpec("") + resolvePath := PathToRawSpec("") loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { - var pathToFile = url.String() + pathToFile := url.String() pathToFile = path.Clean(pathToFile) getSpec, ok := resolvePath[pathToFile] if !ok { diff --git a/rules_openapi/internal/generate.bzl b/rules_openapi/internal/generate.bzl index 8b2cda5f2..9a03533e6 100644 --- a/rules_openapi/internal/generate.bzl +++ b/rules_openapi/internal/generate.bzl @@ -81,9 +81,9 @@ openapi_generate_go = rule( ), "_oapi_codegen": attr.label( doc = "The code generator binary.", - default = "@com_github_deepmap_oapi_codegen//cmd/oapi-codegen:oapi-codegen", + default = "@com_github_deepmap_oapi_codegen_v2//cmd/oapi-codegen:oapi-codegen", executable = True, - cfg = "target", + cfg = "exec", ), "out_types": attr.output( doc = "The generated types file.", diff --git a/rules_openapi/internal/tools.go b/rules_openapi/internal/tools.go new file mode 100644 index 000000000..618a3b556 --- /dev/null +++ b/rules_openapi/internal/tools.go @@ -0,0 +1,24 @@ +// Copyright 2023 SCION Association +// +// 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. + +//go:build tools + +package rulesopenapi + +import ( + // The bazel rule openapi_generate_go uses oapi-codegen as a build tool. + // As an easy way to ensure that we have all the appropriate dependencies, + // import it here in this dummy go file. + _ "github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen" +) From cab6ce389b5ba96c5e7cdbaf0591ffca99aafd42 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Fri, 3 Nov 2023 09:34:51 +0100 Subject: [PATCH 081/255] tools: specify project name in docker-compose files (#4396) Simplify the usage of the various docker-compose configurations by including the project name in the configuration file. This has been supported for a while now in docker-compose v2. This allows to drop the `-p`/`--project-name` from all `docker-compose` incantations. Also, streamline the docker-compose files generated by the topogen scripts; remove the explicit `container_name` configurations and drop all the explicit `scion_` prefixes -- managing these prefixes is docker-compose's job. Shut up the warnings on "SCION_EXPERIMENTAL_... variable is not set. Defaulting to a blank string." by using the variable expansion syntax to explicitly default to a blank string. Also, drop the `docker compose` `--compatibility` flag. The compatibility flag affects what word separator is used in the container name and it has long been deprecated. We don't usually rely on specific container names, so this should be fine. In some exception cases where expecting specific container names seems more practical (containers for bazel-remote-cache and go-module-proxy) due to special casing in the CI scripts, container_name is set explicitly. --- .buildkite/hooks/bazel-remote.yml | 1 + .buildkite/hooks/go-module-proxy.yml | 1 + .buildkite/hooks/pre-command | 4 +- acceptance/cert_renewal/test.py | 4 +- acceptance/common/docker.py | 6 +-- acceptance/hidden_paths/test.py | 46 +++++++++----------- acceptance/sig_short_exp_time/test | 14 +++--- acceptance/topo_cs_reload/docker-compose.yml | 2 - acceptance/topo_cs_reload/reload_test.go | 18 +++----- acceptance/topo_daemon_reload/reload_test.go | 13 +++--- acceptance/trc_update/test.py | 2 +- bazel-remote.yml | 1 + demo/drkey/test.py | 9 ++-- demo/file_transfer/file_transfer.py | 5 +-- scion.sh | 4 +- tools/dc | 3 +- tools/integration/docker.go | 5 +-- tools/topology/common.py | 4 -- tools/topology/docker.py | 32 ++++++-------- tools/topology/docker_utils.py | 7 ++- tools/topology/monitoring.py | 4 +- tools/topology/sig.py | 23 ++++------ 22 files changed, 86 insertions(+), 122 deletions(-) diff --git a/.buildkite/hooks/bazel-remote.yml b/.buildkite/hooks/bazel-remote.yml index 07523b1c2..b4fdae7b2 100644 --- a/.buildkite/hooks/bazel-remote.yml +++ b/.buildkite/hooks/bazel-remote.yml @@ -1,4 +1,5 @@ version: "2.4" +name: bazel_remote services: bazel-remote: container_name: bazel-remote-cache diff --git a/.buildkite/hooks/go-module-proxy.yml b/.buildkite/hooks/go-module-proxy.yml index 4c852825f..566068cca 100644 --- a/.buildkite/hooks/go-module-proxy.yml +++ b/.buildkite/hooks/go-module-proxy.yml @@ -1,5 +1,6 @@ --- version: "2.4" +name: athens services: go-module-proxy: container_name: go-module-proxy diff --git a/.buildkite/hooks/pre-command b/.buildkite/hooks/pre-command index ada7f07ae..38f630752 100755 --- a/.buildkite/hooks/pre-command +++ b/.buildkite/hooks/pre-command @@ -43,7 +43,7 @@ echo "~~~ Starting bazel remote cache proxy" # Start bazel remote cache proxy for S3 # Note that S3 keys are injected by buildkite, see # https://buildkite.com/docs/pipelines/secrets#storing-secrets-with-the-elastic-ci-stack-for-aws -docker compose --compatibility -f .buildkite/hooks/bazel-remote.yml -p bazel_remote up -d +docker compose -f .buildkite/hooks/bazel-remote.yml up -d echo "~~~ Starting go module proxy" -docker compose --compatibility -f .buildkite/hooks/go-module-proxy.yml -p athens up -d +docker compose -f .buildkite/hooks/go-module-proxy.yml up -d diff --git a/acceptance/cert_renewal/test.py b/acceptance/cert_renewal/test.py index 799fa4225..2a3a9ef30 100755 --- a/acceptance/cert_renewal/test.py +++ b/acceptance/cert_renewal/test.py @@ -72,9 +72,9 @@ def _run(self): end2end.run_fg() logger.info("==> Shutting down control servers and purging caches") - for container in self.dc.list_containers("scion_sd.*"): + for container in self.dc.list_containers("sd.*"): self.dc("rm", container) - for container in self.dc.list_containers("scion_cs.*"): + for container in self.dc.list_containers("cs.*"): self.dc.stop_container(container) for cs_config in cs_configs: files = list((pathlib.Path(self.artifacts) / diff --git a/acceptance/common/docker.py b/acceptance/common/docker.py index e4a1b7014..0af9a69bc 100644 --- a/acceptance/common/docker.py +++ b/acceptance/common/docker.py @@ -35,15 +35,12 @@ from plumbum import cmd SCION_DC_FILE = "gen/scion-dc.yml" -DC_PROJECT = "scion" SCION_TESTING_DOCKER_ASSERTIONS_OFF = 'SCION_TESTING_DOCKER_ASSERTIONS_OFF' class Compose(object): def __init__(self, - project: str = DC_PROJECT, compose_file: str = SCION_DC_FILE): - self.project = project self.compose_file = compose_file def __call__(self, *args, **kwargs) -> str: @@ -51,8 +48,7 @@ def __call__(self, *args, **kwargs) -> str: # Note: not using plumbum here due to complications with encodings in the captured output try: res = subprocess.run( - ["docker", "compose", "--compatibility", - "-f", self.compose_file, "-p", self.project, *args], + ["docker", "compose", "-f", self.compose_file, *args], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8") except subprocess.CalledProcessError as e: raise _CalledProcessErrorWithOutput(e) from None diff --git a/acceptance/hidden_paths/test.py b/acceptance/hidden_paths/test.py index cf0d3ae43..90bc3101c 100755 --- a/acceptance/hidden_paths/test.py +++ b/acceptance/hidden_paths/test.py @@ -5,10 +5,9 @@ import http.server import threading -from plumbum import cmd - from acceptance.common import base from acceptance.common import scion +from tools.topology.scion_addr import ISD_AS class Test(base.TestTopogen): @@ -108,12 +107,6 @@ def setup_start(self): super().setup_start() - self._testers = { - "2": "tester_1-ff00_0_2", - "3": "tester_1-ff00_0_3", - "4": "tester_1-ff00_0_4", - "5": "tester_1-ff00_0_5", - } self._ases = { "2": "1-ff00:0:2", "3": "1-ff00:0:3", @@ -126,27 +119,30 @@ def _run(self): self._server.shutdown() # by now configuration must have been downloaded everywhere # Group 3 - self._showpaths_bidirectional("2", "3", 0) - self._showpaths_bidirectional("2", "5", 0) - self._showpaths_bidirectional("3", "5", 0) + self._showpaths_bidirectional("2", "3") + self._showpaths_bidirectional("2", "5") + self._showpaths_bidirectional("3", "5") # Group 4 - self._showpaths_bidirectional("2", "4", 0) - self._showpaths_bidirectional("2", "5", 0) - self._showpaths_bidirectional("4", "5", 0) + self._showpaths_bidirectional("2", "4") + self._showpaths_bidirectional("2", "5") + self._showpaths_bidirectional("4", "5") # Group 3 X 4 - self._showpaths_bidirectional("3", "4", 1) - - def _showpaths_bidirectional(self, source: str, destination: str, retcode: int): - self._showpaths_run(source, destination, retcode) - self._showpaths_run(destination, source, retcode) - - def _showpaths_run(self, source_as: str, destination_as: str, retcode: int): - print(cmd.docker("exec", "-t", self._testers[source_as], "scion", - "sp", self._ases[destination_as], - "--timeout", "2s", - retcode=retcode)) + try: + self._showpaths_bidirectional("3", "4") + except Exception as e: + print(e) + else: + raise AssertionError("Unexpected success; should not have paths 3 -> 4") + + def _showpaths_bidirectional(self, source: str, destination: str): + self._showpaths_run(source, destination) + self._showpaths_run(destination, source) + + def _showpaths_run(self, source_as: str, destination_as: str): + print(self.execute_tester(ISD_AS(self._ases[source_as]), + "scion", "sp", self._ases[destination_as], "--timeout", "2s")) def configuration_server(server): diff --git a/acceptance/sig_short_exp_time/test b/acceptance/sig_short_exp_time/test index 10bc25eb2..55bd70485 100755 --- a/acceptance/sig_short_exp_time/test +++ b/acceptance/sig_short_exp_time/test @@ -55,24 +55,24 @@ run_test() {(set -e docker image load -i acceptance/sig_short_exp_time/sig1.tar docker image load -i acceptance/sig_short_exp_time/sig2.tar - docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml up -d dispatcher1 dispatcher2 sig1 sig2 patha pathb + docker compose -f acceptance/sig_short_exp_time/docker-compose.yml up -d dispatcher1 dispatcher2 sig1 sig2 patha pathb # Set up forward route on network stack 1 and 2 through the sig tunnel # device. The route is a property of the network stack, and persists after # the container that added it has exited. # # If the route configuration fails, the test is not stopped. - docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml run --name route1 --rm tester1 ip route add 242.254.200.2/32 dev sig || true - docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml run --name route2 --rm tester2 ip route add 242.254.100.2/32 dev sig || true + docker compose -f acceptance/sig_short_exp_time/docker-compose.yml run --name route1 --rm tester1 ip route add 242.254.200.2/32 dev sig || true + docker compose -f acceptance/sig_short_exp_time/docker-compose.yml run --name route2 --rm tester2 ip route add 242.254.100.2/32 dev sig || true echo "Start background ping, ping every 0.2 seconds" - docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml run --name tester1 -d tester1 ping -i 0.2 242.254.200.2 + docker compose -f acceptance/sig_short_exp_time/docker-compose.yml run --name tester1 -d tester1 ping -i 0.2 242.254.200.2 echo "Waiting 10 seconds for path A to expire..." sleep 10 echo "Path A expired, simulating it by shutting down path A proxy" # Traffic should have switched beforehand to path b, and no pings should be lost - docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml stop patha + docker compose -f acceptance/sig_short_exp_time/docker-compose.yml stop patha sleep 1 docker kill -s SIGINT tester1 @@ -104,9 +104,9 @@ OUTPUT_DIR=$TEST_UNDECLARED_OUTPUTS_DIR mkdir -p $OUTPUT_DIR/logs for CNTR in sig1 sig2 dispatcher1 dispatcher2; do - docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml logs "$CNTR" > "$OUTPUT_DIR/logs/$CNTR.log" + docker compose -f acceptance/sig_short_exp_time/docker-compose.yml logs "$CNTR" > "$OUTPUT_DIR/logs/$CNTR.log" done -docker compose --compatibility -f acceptance/sig_short_exp_time/docker-compose.yml down -v +docker compose -f acceptance/sig_short_exp_time/docker-compose.yml down -v exit $RC diff --git a/acceptance/topo_cs_reload/docker-compose.yml b/acceptance/topo_cs_reload/docker-compose.yml index 00591e140..ba010d1f7 100644 --- a/acceptance/topo_cs_reload/docker-compose.yml +++ b/acceptance/topo_cs_reload/docker-compose.yml @@ -8,7 +8,6 @@ networks: - subnet: 242.253.100.0/24 services: topo_cs_reload_dispatcher: - container_name: topo_cs_reload_dispatcher image: bazel/acceptance/topo_cs_reload:dispatcher networks: bridge1: @@ -16,7 +15,6 @@ services: volumes: - vol_topo_cs_reload_disp:/run/shm/dispatcher:rw topo_cs_reload_control_srv: - container_name: topo_cs_reload_control_srv image: bazel/acceptance/topo_cs_reload:control depends_on: - topo_cs_reload_dispatcher diff --git a/acceptance/topo_cs_reload/reload_test.go b/acceptance/topo_cs_reload/reload_test.go index 53186c642..53f1742d9 100644 --- a/acceptance/topo_cs_reload/reload_test.go +++ b/acceptance/topo_cs_reload/reload_test.go @@ -100,27 +100,23 @@ func setupTest(t *testing.T) testState { require.NoError(t, err) topoFile, err := bazel.Runfile(*topoLocation) require.NoError(t, err) - s.mustExec(t, *genCryptoLocation, scionPKI, - "crypto.tar", topoFile, cryptoLib) + s.mustExec(t, *genCryptoLocation, scionPKI, "crypto.tar", topoFile, cryptoLib) s.mustExec(t, "tar", "-xf", "crypto.tar", "-C", tmpDir) // first load the docker images from bazel into the docker deamon, the // tars are in the same folder as this test runs in bazel. s.mustExec(t, "docker", "image", "load", "-i", "dispatcher.tar") s.mustExec(t, "docker", "image", "load", "-i", "control.tar") // now start the docker containers - s.mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", - "up", "-d") + s.mustExec(t, "docker", "compose", "-f", "docker-compose.yml", "up", "-d") // wait a bit to make sure the containers are ready. time.Sleep(time.Second / 2) t.Log("Test setup done") - s.mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", - "ps") + s.mustExec(t, "docker", "compose", "-f", "docker-compose.yml", "ps") return s } func (s testState) teardownTest(t *testing.T) { - defer s.mustExec(t, "docker", "compose", "--compatibility", - "-f", "docker-compose.yml", "down", "-v") + defer s.mustExec(t, "docker", "compose", "-f", "docker-compose.yml", "down", "-v") outdir, exists := os.LookupEnv("TEST_UNDECLARED_OUTPUTS_DIR") require.True(t, exists, "TEST_UNDECLARED_OUTPUTS_DIR must be defined") @@ -130,7 +126,7 @@ func (s testState) teardownTest(t *testing.T) { "topo_cs_reload_dispatcher": "disp.log", "topo_cs_reload_control_srv": "control.log", } { - cmd := exec.Command("docker", "compose", "--compatibility", + cmd := exec.Command("docker", "compose", "-f", "docker-compose.yml", "logs", "--no-color", service) logFileName := fmt.Sprintf("%s/logs/%s", outdir, file) logFile, err := os.Create(logFileName) @@ -149,9 +145,9 @@ func (s testState) teardownTest(t *testing.T) { func (s testState) loadTopo(t *testing.T, name string) { t.Helper() - s.mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + s.mustExec(t, "docker", "compose", "-f", "docker-compose.yml", "exec", "-T", "topo_cs_reload_control_srv", "mv", name, "/topology.json") - s.mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + s.mustExec(t, "docker", "compose", "-f", "docker-compose.yml", "kill", "-s", "SIGHUP", "topo_cs_reload_control_srv") } diff --git a/acceptance/topo_daemon_reload/reload_test.go b/acceptance/topo_daemon_reload/reload_test.go index ee9b9f44b..56802c18b 100644 --- a/acceptance/topo_daemon_reload/reload_test.go +++ b/acceptance/topo_daemon_reload/reload_test.go @@ -71,18 +71,17 @@ func setupTest(t *testing.T) { mustExec(t, "docker", "image", "load", "-i", "dispatcher.tar") mustExec(t, "docker", "image", "load", "-i", "daemon.tar") // now start the docker containers - mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + mustExec(t, "docker", "compose", "-f", "docker-compose.yml", "up", "-d", "topo_daemon_reload_dispatcher", "topo_daemon_reload_daemon") // wait a bit to make sure the containers are ready. time.Sleep(time.Second / 2) t.Log("Test setup done") - mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + mustExec(t, "docker", "compose", "-f", "docker-compose.yml", "ps") } func teardownTest(t *testing.T) { - defer mustExec(t, "docker", "compose", "--compatibility", - "-f", "docker-compose.yml", "down", "-v") + defer mustExec(t, "docker", "compose", "-f", "docker-compose.yml", "down", "-v") outdir, exists := os.LookupEnv("TEST_UNDECLARED_OUTPUTS_DIR") require.True(t, exists, "TEST_UNDECLARED_OUTPUTS_DIR must be defined") @@ -92,7 +91,7 @@ func teardownTest(t *testing.T) { "topo_daemon_reload_dispatcher": "disp.log", "topo_daemon_reload_daemon": "daemon.log", } { - cmd := exec.Command("docker", "compose", "--compatibility", + cmd := exec.Command("docker", "compose", "-f", "docker-compose.yml", "logs", "--no-color", service) logFileName := fmt.Sprintf("%s/logs/%s", outdir, file) @@ -111,9 +110,9 @@ func teardownTest(t *testing.T) { func loadTopo(t *testing.T, name string) { t.Helper() - mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + mustExec(t, "docker", "compose", "-f", "docker-compose.yml", "exec", "-T", "topo_daemon_reload_daemon", "mv", name, "/topology.json") - mustExec(t, "docker", "compose", "--compatibility", "-f", "docker-compose.yml", + mustExec(t, "docker", "compose", "-f", "docker-compose.yml", "kill", "-s", "SIGHUP", "topo_daemon_reload_daemon") } diff --git a/acceptance/trc_update/test.py b/acceptance/trc_update/test.py index eed759f09..2edf26a0b 100755 --- a/acceptance/trc_update/test.py +++ b/acceptance/trc_update/test.py @@ -72,7 +72,7 @@ def _run(self): end2end["-d", "-outDir", artifacts].run_fg() logger.info('==> Shutting down control servers and purging caches') - cs_services = self.dc.list_containers(".*_cs.*") + cs_services = self.dc.list_containers("cs.*") for cs in cs_services: self.dc.stop_container(cs) diff --git a/bazel-remote.yml b/bazel-remote.yml index ba155b199..b98b18c7b 100644 --- a/bazel-remote.yml +++ b/bazel-remote.yml @@ -1,4 +1,5 @@ version: "2.4" +name: bazel_remote services: bazel-remote: container_name: bazel-remote-cache diff --git a/demo/drkey/test.py b/demo/drkey/test.py index 19f08d40c..0a6c58967 100644 --- a/demo/drkey/test.py +++ b/demo/drkey/test.py @@ -71,7 +71,7 @@ def setup_prepare(self): # Enable delegation for tester host on the fast side (server side), i.e. # allow the tester host to directly request the secret value from which # keys can be derived locally for any host. - tester_ip = self._container_ip("scion_disp_tester_%s" % self.server_isd_as.file_fmt()) + tester_ip = self._container_ip("disp_tester_%s" % self.server_isd_as.file_fmt()) cs_config = self._conf_dir(self.server_isd_as) // "cs*-1.toml" scion.update_toml({"drkey.delegation.scmp": [tester_ip]}, cs_config) @@ -82,9 +82,8 @@ def _run(self): # install demo binary in tester containers: drkey_demo = local["realpath"](self.get_executable("drkey-demo").executable).strip() - testers = ["tester_%s" % ia.file_fmt() for ia in {self.server_isd_as, self.client_isd_as}] - for tester in testers: - local["docker"]("cp", drkey_demo, tester + ":/bin/") + for ia in {self.server_isd_as, self.client_isd_as}: + self.dc("cp", drkey_demo, "tester_%s" % ia.file_fmt() + ":/bin/") # Define DRKey protocol identifiers and derivation typ for test for test in [ @@ -134,7 +133,7 @@ def _endhost_ip(self, isd_as: ISD_AS) -> str: """ Determine the IP used for the end host (client or server) in the given ISD-AS """ # The address must be the daemon IP (as it makes requests to the control # service on behalf of the end host application). - return self._container_ip("scion_sd%s" % isd_as.file_fmt()) + return self._container_ip("sd%s" % isd_as.file_fmt()) def _container_ip(self, container: str) -> str: """ Determine the IP of the container """ diff --git a/demo/file_transfer/file_transfer.py b/demo/file_transfer/file_transfer.py index f4ede5068..b5547b3de 100644 --- a/demo/file_transfer/file_transfer.py +++ b/demo/file_transfer/file_transfer.py @@ -43,7 +43,7 @@ def _set_path_count(self, path_count): with open(config_name, "w") as f: json.dump(t, f, indent=2) # Reload the config. - self.dc("kill", "-s", "SIGHUP", "scion_sig_1-ff00_0_111") + self.dc("kill", "-s", "SIGHUP", "sig_1-ff00_0_111") # Give gateway some time to start using the new path count. time.sleep(2) @@ -86,7 +86,6 @@ def setup_prepare(self): with open(scion_dc, "r") as file: dc = yaml.load(file, Loader=yaml.FullLoader) dc["services"]["tc_setup"] = { - "container_name": "tc_setup", "image": "tester:latest", "cap_add": ["NET_ADMIN"], "volumes": [{ @@ -97,7 +96,7 @@ def setup_prepare(self): "entrypoint": ["/bin/sh", "-exc", "ls -l /share; /share/tc_setup.sh scn_000 16.0mbit ;" " /share/tc_setup.sh scn_001 16.0mbit"], - "depends_on": ["scion_br1-ff00_0_111-1", "scion_br1-ff00_0_111-2"], + "depends_on": ["br1-ff00_0_111-1", "br1-ff00_0_111-2"], "network_mode": "host", } with open(scion_dc, "w") as file: diff --git a/scion.sh b/scion.sh index cf851d4f6..7343c35d0 100755 --- a/scion.sh +++ b/scion.sh @@ -6,7 +6,7 @@ cmd_bazel-remote() { mkdir -p "$HOME/.cache/bazel/remote" uid=$(id -u) gid=$(id -g) - USER_ID="$uid" GROUP_ID="$gid" docker compose --compatibility -f bazel-remote.yml -p bazel_remote up -d + USER_ID="$uid" GROUP_ID="$gid" docker compose -f bazel-remote.yml up -d } cmd_topo-clean() { @@ -36,7 +36,7 @@ cmd_topodot() { start_scion() { echo "Running the network..." if is_docker_be; then - docker compose --compatibility -f gen/scion-dc.yml -p scion up -d + docker compose -f gen/scion-dc.yml up -d return 0 else run_setup diff --git a/tools/dc b/tools/dc index a2912882a..4a2951f05 100755 --- a/tools/dc +++ b/tools/dc @@ -76,10 +76,9 @@ cmd_monitoring() { # Runs docker compose for the given project dc() { - local project="$1" local dc_file="gen/$1-dc.yml" shift - COMPOSE_FILE="$dc_file" docker compose --compatibility -p "$project" --ansi never "$@" + COMPOSE_FILE="$dc_file" docker compose --ansi never "$@" } cmd_collect_logs() { diff --git a/tools/integration/docker.go b/tools/integration/docker.go index 055c39183..0b26344a3 100644 --- a/tools/integration/docker.go +++ b/tools/integration/docker.go @@ -38,9 +38,8 @@ var ( var dockerArgs []string func initDockerArgs() { - dockerArgs = []string{"compose", "--compatibility", - "-f", GenFile("scion-dc.yml"), "-p", "scion", "exec", "-T", "-e", - fmt.Sprintf("%s=1", GoIntegrationEnv)} + dockerArgs = []string{"compose", "-f", GenFile("scion-dc.yml"), "exec", "-T", + "-e", fmt.Sprintf("%s=1", GoIntegrationEnv)} } var _ Integration = (*dockerIntegration)(nil) diff --git a/tools/topology/common.py b/tools/topology/common.py index 934725eff..7f9b74a7e 100644 --- a/tools/topology/common.py +++ b/tools/topology/common.py @@ -182,10 +182,6 @@ def sciond_name(topo_id): return 'sd%s' % topo_id.file_fmt() -def sciond_svc_name(topo_id): - return 'scion_%s' % sciond_name(topo_id) - - def json_default(o): if isinstance(o, AddressProxy): return str(o.ip) diff --git a/tools/topology/docker.py b/tools/topology/docker.py index b0594925e..895707059 100644 --- a/tools/topology/docker.py +++ b/tools/topology/docker.py @@ -25,7 +25,7 @@ ArgsTopoDicts, docker_host, docker_image, - sciond_svc_name, + sciond_name, ) from topology.docker_utils import DockerUtilsGenArgs, DockerUtilsGenerator from topology.net import NetworkDescription, IPNetwork @@ -54,6 +54,7 @@ def __init__(self, args): self.args = args self.dc_conf = { 'version': DOCKER_COMPOSE_CONFIG_VERSION, + 'name': 'scion', 'services': {}, 'networks': {}, 'volumes': {} @@ -62,7 +63,6 @@ def __init__(self, args): self.bridges = {} self.output_base = os.environ.get('SCION_OUTPUT_BASE', os.getcwd()) self.user = '%d:%d' % (os.getuid(), os.getgid()) - self.prefix = 'scion_' def generate(self): self._create_networks() @@ -145,18 +145,17 @@ def _br_conf(self, topo_id, topo, base): image = docker_image(self.args, 'posix-router') entry = { 'image': image, - 'container_name': self.prefix + k, 'networks': {}, 'user': self.user, 'volumes': ['%s:/share/conf:ro' % base], 'environment': { 'SCION_EXPERIMENTAL_BFD_DETECT_MULT': - '${SCION_EXPERIMENTAL_BFD_DETECT_MULT}', + '${SCION_EXPERIMENTAL_BFD_DETECT_MULT:-}', 'SCION_EXPERIMENTAL_BFD_DESIRED_MIN_TX': - '${SCION_EXPERIMENTAL_BFD_DESIRED_MIN_TX}', + '${SCION_EXPERIMENTAL_BFD_DESIRED_MIN_TX:-}', 'SCION_EXPERIMENTAL_BFD_REQUIRED_MIN_RX': - '${SCION_EXPERIMENTAL_BFD_REQUIRED_MIN_RX}', + '${SCION_EXPERIMENTAL_BFD_REQUIRED_MIN_RX:-}', }, 'command': ['--config', '/share/conf/%s.toml' % k] } @@ -170,18 +169,16 @@ def _br_conf(self, topo_id, topo, base): entry['networks'][self.bridges[net['net']]] = { '%s_address' % ipv: str(net[ipv]) } - self.dc_conf['services']['scion_%s' % k] = entry + self.dc_conf['services'][k] = entry def _control_service_conf(self, topo_id, topo, base): for k in topo.get("control_service", {}).keys(): entry = { 'image': docker_image(self.args, 'control'), - 'container_name': - self.prefix + k, - 'depends_on': ['scion_disp_%s' % k], + 'depends_on': ['disp_%s' % k], 'network_mode': - 'service:scion_disp_%s' % k, + 'service:disp_%s' % k, 'user': self.user, 'volumes': [ @@ -192,7 +189,7 @@ def _control_service_conf(self, topo_id, topo, base): ], 'command': ['--config', '/share/conf/%s.toml' % k] } - self.dc_conf['services']['scion_%s' % k] = entry + self.dc_conf['services'][k] = entry def _dispatcher_conf(self, topo_id, topo, base): image = 'dispatcher' @@ -221,7 +218,6 @@ def _dispatcher_conf(self, topo_id, topo, base): entry['networks'][self.bridges[net['net']]] = { '%s_address' % ipv: ip } - entry['container_name'] = '%sdisp_%s' % (self.prefix, disp_id) entry['volumes'].append(self._disp_vol(disp_id)) conf = '%s:/share/conf:rw' % base entry['volumes'].append(conf) @@ -229,12 +225,12 @@ def _dispatcher_conf(self, topo_id, topo, base): '--config', '/share/conf/disp_%s.toml' % disp_id ] - self.dc_conf['services']['scion_disp_%s' % disp_id] = entry + self.dc_conf['services']['disp_%s' % disp_id] = entry self.dc_conf['volumes'][self._disp_vol(disp_id).split(':') [0]] = None def _sciond_conf(self, topo_id, base): - name = sciond_svc_name(topo_id) + name = sciond_name(topo_id) net = self.elem_networks["sd" + topo_id.file_fmt()][0] ipv = 'ipv4' if ipv not in net: @@ -245,9 +241,7 @@ def _sciond_conf(self, topo_id, base): 'extra_hosts': ['jaeger:%s' % docker_host(self.args.docker)], 'image': docker_image(self.args, 'daemon'), - 'container_name': - '%ssd%s' % (self.prefix, topo_id.file_fmt()), - 'depends_on': ['scion_disp_%s' % disp_id], + 'depends_on': ['disp_%s' % disp_id], 'user': self.user, 'volumes': [ @@ -266,7 +260,7 @@ def _sciond_conf(self, topo_id, base): self.dc_conf['services'][name] = entry def _disp_vol(self, disp_id): - return 'vol_%sdisp_%s:/run/shm/dispatcher:rw' % (self.prefix, disp_id) + return 'vol_disp_%s:/run/shm/dispatcher:rw' % disp_id def _cache_vol(self): return self.output_base + '/gen-cache:/share/cache:rw' diff --git a/tools/topology/docker_utils.py b/tools/topology/docker_utils.py index fc15124bd..90d4041f5 100644 --- a/tools/topology/docker_utils.py +++ b/tools/topology/docker_utils.py @@ -75,19 +75,18 @@ def _test_conf(self, topo_id): name = 'tester_%s' % topo_id.file_fmt() entry = { 'image': docker_image(self.args, 'tester'), - 'container_name': 'tester_%s' % topo_id.file_fmt(), - 'depends_on': ['scion_disp_%s' % name], + 'depends_on': ['disp_%s' % name], 'privileged': True, 'entrypoint': 'sh tester.sh', 'environment': {}, # 'user': self.user, 'volumes': [ - 'vol_scion_disp_%s:/run/shm/dispatcher:rw' % name, + 'vol_disp_%s:/run/shm/dispatcher:rw' % name, self.output_base + '/logs:' + cntr_base + '/logs:rw', self.output_base + '/gen:' + cntr_base + '/gen:rw', self.output_base + '/gen-certs:' + cntr_base + '/gen-certs:rw' ], - 'network_mode': 'service:scion_disp_%s' % name, + 'network_mode': 'service:disp_%s' % name, } net = self.args.networks[name][0] ipv = 'ipv4' diff --git a/tools/topology/monitoring.py b/tools/topology/monitoring.py index 930a7b521..974dde527 100644 --- a/tools/topology/monitoring.py +++ b/tools/topology/monitoring.py @@ -166,13 +166,12 @@ def _write_disp_file(self): def _write_dc_file(self): # Merged yeager and prometheus files. - name = 'monitoring' monitoring_dc = { 'version': DOCKER_COMPOSE_CONFIG_VERSION, + 'name': 'monitoring', 'services': { 'prometheus': { 'image': 'prom/prometheus:v2.47.2', - 'container_name': name+'prometheus', 'network_mode': 'host', 'volumes': [ self.output_base + '/gen:/prom-config:ro' @@ -181,7 +180,6 @@ def _write_dc_file(self): }, 'jaeger': { 'image': 'jaegertracing/all-in-one:1.22.0', - 'container_name': name+'yeager', 'user': '%s:%s' % (str(os.getuid()), str(os.getgid())), 'ports': [ '6831:6831/udp', diff --git a/tools/topology/sig.py b/tools/topology/sig.py index 9ddd2121e..73c4fee21 100644 --- a/tools/topology/sig.py +++ b/tools/topology/sig.py @@ -23,7 +23,7 @@ from topology.common import ( ArgsBase, json_default, - sciond_svc_name, + sciond_name, SD_API_PORT, SIG_CONFIG_NAME, translate_features, @@ -55,7 +55,6 @@ def __init__(self, args): self.dc_conf = args.dc_conf self.user = '%d:%d' % (os.getuid(), os.getgid()) self.output_base = os.environ.get('SCION_OUTPUT_BASE', os.getcwd()) - self.prefix = '' def generate(self): for topo_id, topo in self.args.topo_dicts.items(): @@ -72,8 +71,6 @@ def _dispatcher_conf(self, topo_id, base): entry = { 'image': 'dispatcher', - 'container_name': - 'scion_%sdisp_sig_%s' % (self.prefix, topo_id.file_fmt()), 'depends_on': { 'utils_chowner': { 'condition': 'service_started' @@ -98,15 +95,14 @@ def _dispatcher_conf(self, topo_id, base): entry['networks'][self.args.bridges[net['net']]] = { '%s_address' % ipv: str(net[ipv]) } - self.dc_conf['services']['scion_disp_sig_%s' % + self.dc_conf['services']['disp_sig_%s' % topo_id.file_fmt()] = entry - vol_name = 'vol_scion_%sdisp_sig_%s' % (self.prefix, - topo_id.file_fmt()) + vol_name = 'vol_disp_sig_%s' % topo_id.file_fmt() self.dc_conf['volumes'][vol_name] = None def _sig_dc_conf(self, topo_id, base): - setup_name = 'scion_sig_setup_%s' % topo_id.file_fmt() - disp_id = 'scion_disp_sig_%s' % topo_id.file_fmt() + setup_name = 'sig_setup_%s' % topo_id.file_fmt() + disp_id = 'disp_sig_%s' % topo_id.file_fmt() self.dc_conf['services'][setup_name] = { 'image': 'tester:latest', 'depends_on': [disp_id], @@ -114,14 +110,12 @@ def _sig_dc_conf(self, topo_id, base): 'privileged': True, 'network_mode': 'service:%s' % disp_id, } - self.dc_conf['services']['scion_sig_%s' % topo_id.file_fmt()] = { + self.dc_conf['services']['sig_%s' % topo_id.file_fmt()] = { 'image': 'posix-gateway:latest', - 'container_name': - 'scion_%ssig_%s' % (self.prefix, topo_id.file_fmt()), 'depends_on': [ disp_id, - sciond_svc_name(topo_id), + sciond_name(topo_id), setup_name, ], 'environment': { @@ -196,5 +190,4 @@ def _sig_toml(self, topo_id, topo): write_file(path, toml.dumps(sig_conf)) def _disp_vol(self, topo_id): - return 'vol_scion_%sdisp_sig_%s:/run/shm/dispatcher:rw' % ( - self.prefix, topo_id.file_fmt()) + return 'vol_disp_sig_%s:/run/shm/dispatcher:rw' % topo_id.file_fmt() From 3beb210bf5714a80718dcf226c21fd893e3aea76 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Mon, 13 Nov 2023 15:05:05 +0100 Subject: [PATCH 082/255] build: make git-version not fail if no tags exist (#4438) --always, will substitute an abbreviated commit hash if there's no tag in sight. Better than failing with a cryptic message. --- tools/git-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/git-version b/tools/git-version index a81a5e122..c9b09787b 100755 --- a/tools/git-version +++ b/tools/git-version @@ -2,4 +2,4 @@ # Small script to determine the git version. -exec git describe --tags --dirty +exec git describe --tags --dirty --always From 2136a634bba330c133b0bee1a0737fdf78453834 Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Fri, 17 Nov 2023 10:15:14 +0100 Subject: [PATCH 083/255] testing: add router benchmark program and use it as integration test (#4437) * Enhance the end2end_integration programs as follows: * end2end_integration has a slightly finer-grain role-based pair selection capability. * end2end_integration outputs an extra result line that provides precise start/stop timestamps for the whole test. * process_metrics exposes the number of cores used by Go. * Add end2endblast. Similar to end2end but plays a game other than pingpong: packetblast. It keeps logging and tracing to a minimum. The server side responds to very few of the pings (1/256). Just enough to prove that the circuit works. * Add an integration test called router_benchmark: * relies on an especially crafted topology: router_bm.topo * uses end2end_integration with command end2endblast over that topology as a load test for the router * extracts and logs relevant performance metrics after the test * compares performances with a set of expectations if executed by CI. As a benchmark program, this is only a first approximation. Extending the end2end suite provided a quick solution but isn't ideal: it uses too many cores at once due to requiring 5 routers actively running for one of the tests. More work is in progress to replace this with some leaner setup where only one router is actually running. --- BUILD.bazel | 1 + acceptance/router_benchmark/BUILD.bazel | 12 + acceptance/router_benchmark/test.py | 302 ++++++++++++ .../router_benchmark/testdata/router_bm.topo | 25 + doc/manuals/router.rst | 30 +- docker/tester.bzl | 1 + .../processmetrics/processmetrics_linux.go | 68 +-- router/config/config.go | 7 + tools/end2end/main.go | 31 +- tools/end2end_integration/BUILD.bazel | 4 + tools/end2end_integration/main.go | 50 +- tools/end2endblast/BUILD.bazel | 30 ++ tools/end2endblast/main.go | 459 ++++++++++++++++++ tools/integration/integrationlib/common.go | 36 +- tools/md/skipped | 1 + topology/BUILD.bazel | 1 + 16 files changed, 997 insertions(+), 61 deletions(-) create mode 100644 acceptance/router_benchmark/BUILD.bazel create mode 100755 acceptance/router_benchmark/test.py create mode 100644 acceptance/router_benchmark/testdata/router_bm.topo create mode 100644 tools/end2endblast/BUILD.bazel create mode 100644 tools/end2endblast/main.go diff --git a/BUILD.bazel b/BUILD.bazel index 17a531069..c43159ca4 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -198,6 +198,7 @@ pkg_tar( "//tools/buildkite/cmd/buildkite_artifacts", "//tools/end2end", "//tools/end2end_integration", + "//tools/end2endblast", "//tools/pktgen/cmd/pktgen", "//tools/scion_integration", "//tools/udpproxy", diff --git a/acceptance/router_benchmark/BUILD.bazel b/acceptance/router_benchmark/BUILD.bazel new file mode 100644 index 000000000..824a7271b --- /dev/null +++ b/acceptance/router_benchmark/BUILD.bazel @@ -0,0 +1,12 @@ +load("//acceptance/common:topogen.bzl", "topogen_test") + +topogen_test( + name = "test", + src = "test.py", + args = [ + "--executable=end2end_integration:$(location //tools/end2end_integration)", + ], + data = ["//tools/end2end_integration"], + homedir = "$(rootpath //tools/end2end_integration)", + topo = "testdata/router_bm.topo", +) diff --git a/acceptance/router_benchmark/test.py b/acceptance/router_benchmark/test.py new file mode 100755 index 000000000..2049d9eea --- /dev/null +++ b/acceptance/router_benchmark/test.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python3 + +# Copyright 2023 SCION Association +# +# 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. + +import logging +import json +import yaml +from http.client import HTTPConnection +from urllib.parse import urlencode +from plumbum import cli +from plumbum.cmd import cat, grep, wc + +from acceptance.common import base, docker + +logger = logging.getLogger(__name__) + +# This test relies ona specific topology router_bm.topo. +# This topology is 1 core AS with two children and one core AS with none like so: +# +# CoreAS-A CoreAS-B +# BR-A1 BR-A2 ---- BR-B +# | | +# BR-C BR-D +# AS-C AS-D + +# Those values are valid expectations only when running in the CI environment. +EXPECTATIONS = { + 'in': 53000, + 'out': 26000, + 'in_transit': 73000, + 'out_transit': 49000, + 'br_transit': 73000, +} + + +class Test(base.TestTopogen): + """ + Tests that the performance of the router is within a satisfying (TBD) range. + The test runs in a bespoke topology. + """ + + ci = cli.Flag( + "ci", + help="Do extra checks for CI", + envname="CI" + ) + + def setup_prepare(self): + super().setup_prepare() + + # The expected topology for this test is well-known: see router_bm.topo + # This test is configured to match. + + # Distribute available cores among routers. The base schema is expressed as fractions of 12. + # Then we scale and round. + + childRouterCores = 2 # *2 + farRouterCores = 2 # *1 + centerRouterCores = 3 # *2 + availCores = int((cat['/proc/cpuinfo'] | grep['processor\\s:'] | wc['-l'])()) + + childRouterCores = int(childRouterCores * availCores / 12) + farRouterCores = int(farRouterCores * availCores / 12) + centerRouterCores = int(centerRouterCores * availCores / 12) + + if childRouterCores < 1: + childRouterCores = 1 + + if farRouterCores < 1: + farRouterCores = 1 + + if centerRouterCores < 1: + centerRouterCores = 1 + + availCores -= (2 * childRouterCores + 2 * centerRouterCores + farRouterCores) + + # The truncations can leave us with up to 4 extra cores. Give first to the center routers, + # if there's enough. + if availCores > 1: + availCores -= 2 + centerRouterCores += 1 + + # The leftovers go to childRouterCores, even if it means allocating one extraneous core. + if availCores > 0: + childRouterCores += 1 + + coreCountUpdates = { + 'br1-ff00_0_110-1': centerRouterCores, + 'br1-ff00_0_110-2': centerRouterCores, + 'br1-ff00_0_111-1': childRouterCores, + 'br1-ff00_0_112-1': childRouterCores, + 'br2-ff00_0_120-1': farRouterCores, + } + + # Edit GOMAXPROC for all routers in the docker compose file. + scion_dc = self.artifacts / "gen/scion-dc.yml" + with open(scion_dc, "r") as file: + dc = yaml.load(file, Loader=yaml.FullLoader) + + for router, coreCnt in coreCountUpdates.items(): + dc["services"][router]["environment"]["GOMAXPROCS"] = f"{coreCnt}" + + with open(scion_dc, "w") as file: + yaml.dump(dc, file) + + def setup(self): + super().setup() + self.monitoring_dc = docker.Compose(compose_file=self.artifacts / "gen/monitoring-dc.yml") + self.monitoring_dc("up", "-d") + + def _run(self): + # Give some time for the topology to start. + self.await_connectivity() + + # Start as-transiting load. With the router_bm topology + + # The subset noncore#nonlocalcore gives us outgoing traffic at each + # child, incoming traffic at BR-B, AS-transit-in traffic at BR-A1, + # and AS-transit-out traffic at BR-A2. There is a small amount of + # in and out traffic everywhere, on top of that produced by the test. + # We only consider the routers involved in the test. Those see much + # higher rates... we use that to isolate them in the results without + # having to compare instance labels with the topology data. + logger.info("==> Starting load as-transit") + loadtest = self.get_executable("end2end_integration") + retCode, stdOut, stdErr = loadtest[ + "-d", + "-outDir", self.artifacts, + "-name", "router_benchmark", + "-cmd", "./bin/end2endblast", + "-attempts", 1500000, + "-timeout", "120s", # Timeout is for all attempts together + "-parallelism", 100, + "-subset", "noncore#core#remoteISD" + ].run_tee() + + for line in stdOut.splitlines(): + if line.startswith('metricsBegin'): + _, beg, _, end = line.split() + + logger.info('==> Collecting in/out/as-transit performance metrics...') + + # The raw metrics are expressed in terms of core*seconds. We convert to machine*seconds + # which allows us to provide a projected packet/s; ...more intuitive than packets/core*s. + # We measure the rate over 10s. For best results we sample the end of the middle 10s of the + # run. "beg" is the start time of the real action and "end" is the end time. + sampleTime = (int(beg) + int(end) + 10) / 2 + promQuery = urlencode({ + 'time': f'{sampleTime}', + 'query': ( + 'sum by (instance, job, type) (' + ' rate(router_output_pkts_total{job="BR"}[10s])' + ')' + '/ on (instance, job) group_left()' + 'sum by (instance, job) (' + ' 1 - (rate(process_runnable_seconds_total[10s])' + ' / go_sched_maxprocs_threads)' + ')' + ) + }) + conn = HTTPConnection("localhost:9090") + conn.request('GET', f'/api/v1/query?{promQuery}') + resp = conn.getresponse() + if resp.status != 200: + raise RuntimeError(f'Unexpected response: {resp.status} {resp.reason}') + + pld = json.loads(resp.read().decode('utf-8')) + results = pld['data']['result'] + rateMap = {} + for result in results: + tt = result['metric']['type'] + ts, val = result['value'] + # 0 values should not enter in any averaging. In this test, a very + # low rate means that the router wasn't involved in the test for + # that traffic type. "Out" traffic is the only one that exists at + # two routers. To cover that case, we average the rates for a given + # traffic type. + # TODO: figure a more reliable way to identify the tested routers. + r = int(float(val)) + if r < 5000: # Not a router of interest. + continue + if rateMap.get(tt) is None: + rateMap[tt] = [] + rateMap[tt].append(r) + for tt, rates in rateMap.items(): + total = 0 + for r in rates: + total += r + rateMap[tt] = int(total / len(rates)) + + # Start br-transiting load. + # The subset noncore#noncore gives us a mix of in and out traffic at + # the childrem and pure BR-transit traffic at BR-A1. + logger.info("==> Starting load br-transit") + loadtest = self.get_executable("end2end_integration") + retCode, stdOut, stdErr = loadtest[ + "-d", + "-outDir", self.artifacts, + "-name", "router_benchmark", + "-cmd", "./bin/end2endblast", + "-attempts", 1500000, + "-timeout", "120s", # Timeout is for all attempts together + "-parallelism", 100, + "-subset", "noncore#noncore#remoteAS" + ].run_tee() + + for line in stdOut.splitlines(): + if line.startswith('metricsBegin'): + _, beg, _, end = line.split() + + logger.info('==> Collecting br-transit performance metrics...') + + # The raw metrics are expressed in terms of core*seconds. We convert to machine*seconds + # which allows us to provide a projected packet/s; ...more intuitive than packets/core*s. + # We're interested only in br_transit traffic. We measure the rate over 10s. For best + # results we sample the end of the middle 10s of the run. "beg" is the start time of the + # real action and "end" is the end time. + sampleTime = (int(beg) + int(end) + 10) / 2 + promQuery = urlencode({ + 'time': f'{sampleTime}', + 'query': ( + 'sum by (instance, job) (' + ' rate(router_output_pkts_total{job="BR", type="br_transit"}[10s])' + ')' + '/ on (instance, job) group_left()' + 'sum by (instance, job) (' + ' 1 - (rate(process_runnable_seconds_total[10s])' + ' / go_sched_maxprocs_threads)' + ')' + ) + }) + conn = HTTPConnection("localhost:9090") + conn.request('GET', f'/api/v1/query?{promQuery}') + resp = conn.getresponse() + if resp.status != 200: + raise RuntimeError(f'Unexpected response: {resp.status} {resp.reason}') + + # There's only one router that has br_transit traffic. + pld = json.loads(resp.read().decode('utf-8')) + results = pld['data']['result'] + tt = 'br_transit' + rateMap[tt] = 0 + for result in results: + ts, val = result['value'] + r = int(float(val)) + if r != 0: + rateMap[tt] = r + + # Fetch and log the number of cores used by Go. This may inform performance + # modeling later. + logger.info('==> Collecting number of cores...') + promQuery = urlencode({ + 'query': 'go_sched_maxprocs_threads{job="BR"}' + }) + + conn = HTTPConnection("localhost:9090") + conn.request('GET', f'/api/v1/query?{promQuery}') + resp = conn.getresponse() + if resp.status != 200: + raise RuntimeError(f'Unexpected response: {resp.status} {resp.reason}') + + pld = json.loads(resp.read().decode('utf-8')) + results = pld['data']['result'] + for result in results: + instance = result['metric']['instance'] + _, val = result['value'] + logger.info(f'Router Cores for {instance}: {int(val)}') + + # Log and check the performance... + # If this is used as a CI test. Make sure that the performance is within the expected + # ballpark. + rateTooLow = [] + for tt, exp in EXPECTATIONS.items(): + if self.ci: + logger.info(f'Packets/(machine*s) for {tt}: {rateMap[tt]} expected: {exp}') + if rateMap[tt] < 0.8 * exp: + rateTooLow.append(tt) + else: + logger.info(f'Packets/(machine*s) for {tt}: {rateMap[tt]}') + + if len(rateTooLow) != 0: + raise RuntimeError(f'Insufficient performance for: {rateTooLow}') + + def teardown(self): + self.monitoring_dc("down") + super().teardown() + + +if __name__ == '__main__': + base.main(Test) diff --git a/acceptance/router_benchmark/testdata/router_bm.topo b/acceptance/router_benchmark/testdata/router_bm.topo new file mode 100644 index 000000000..777144615 --- /dev/null +++ b/acceptance/router_benchmark/testdata/router_bm.topo @@ -0,0 +1,25 @@ +--- # Bespoke Topology for router benchmarking: +# Designed to cause at least one router to see only a single type of traffic +# (in/out/asTransitIn/asTransitOut/brTransit) for a well chosen pair type +# (core:core, core:non-core, core:local-core, etc.). +ASes: + "1-ff00:0:110": + core: true + voting: true + authoritative: true + issuing: true + mtu: 1400 + "2-ff00:0:120": + core: true + voting: true + authoritative: true + issuing: true + mtu: 1400 + "1-ff00:0:111": + cert_issuer: 1-ff00:0:110 + "1-ff00:0:112": + cert_issuer: 1-ff00:0:110 +links: + - {a: "1-ff00:0:110-A#1", b: "1-ff00:0:111#1", linkAtoB: CHILD, mtu: 1280} + - {a: "1-ff00:0:110-A#2", b: "1-ff00:0:112#1", linkAtoB: CHILD, mtu:1280} + - {a: "1-ff00:0:110-B#3", b: "2-ff00:0:120#1", linkAtoB: CORE, mtu: 1280} diff --git a/doc/manuals/router.rst b/doc/manuals/router.rst index c68768754..1d70764cd 100644 --- a/doc/manuals/router.rst +++ b/doc/manuals/router.rst @@ -120,6 +120,21 @@ Environment Variables :Type: :ref:`duration ` :Default: ``5m`` +.. envvar:: GOMAXPROCS + + Specified by the GO runtime. The Go runtime starts a number kernel threads such that the number + of non-sleeping threads never exceeds ``GOMAXPROCS``. By default ``GOMAXPROCS`` is equal to the + number of cores in the host. That value can be changed via the ``GOMAXPROCS`` environment + variable (or programatically by the application code). See + `the go runtime documentation `_ + for more information. One reason to change this is running multiple routers on the same host. + In such a case, it is best to split the available cores among the routers, lest Go's default + assumptions causes them to compete for cores and incurr futile context switching. This precaution + is especially useful in performance testing situations. + + :Type: unsigned integer + :Default: ``all cores`` + Configuration ============= @@ -182,17 +197,20 @@ considers the following options. .. option:: router.num_processors = (Default: GOMAXPROCS) Number of goroutines started for SCION packets processing. + These goroutines make the routing decision for the SCION packets by inspecting, validating and updating the path information in the packet header. Packets are processed asynchronously from the corresponding read/write operations on the individual interface sockets. `Goroutines `_ - are the Go pramming language's light-weight user-space concurrency primitives. Go's runtime schedules - goroutines on top of a fixed number of kernel threads. The number of kernel threads is controlled by - the ``GOMAXPROCS`` environment variable. See also the `go runtime documentation `_. - - By default, the router uses ``GOMAXPROCS`` packet processor goroutines, i.e. exactly one goroutine for - each kernel thread created by the runtime. + are the Go programming language's light-weight user-space concurrency primitives. Go's runtime + schedules goroutines on top of a smaller number of kernel threads. The default is to use as + many packet processors as there are kernel threads started by Go, letting other goroutines + displace them sporadically. Whether more or fewer processors are preferable is to be determined + experimentaly. + + The number of kernel threads that go creates depends on the number of usable cores, which is + controlled by the environment variable ``GOMAXPROCS``. See :envvar:`GOMAXPROCS`. .. option:: router.num_slow_processors = (Default: 1) diff --git a/docker/tester.bzl b/docker/tester.bzl index 3c85f2fc7..0e0cbe28f 100644 --- a/docker/tester.bzl +++ b/docker/tester.bzl @@ -33,6 +33,7 @@ def build_tester_image(): name = "bin", srcs = [ "//tools/end2end:end2end", + "//tools/end2endblast:end2endblast", "//scion/cmd/scion", "//scion-pki/cmd/scion-pki:scion-pki", ], diff --git a/pkg/private/processmetrics/processmetrics_linux.go b/pkg/private/processmetrics/processmetrics_linux.go index 821bd34db..3132fa625 100644 --- a/pkg/private/processmetrics/processmetrics_linux.go +++ b/pkg/private/processmetrics/processmetrics_linux.go @@ -12,34 +12,42 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package processmetrics provides a custom collector to export process-level -// metrics beyond what prometheus.ProcesssCollector offers. -// This implementation is restricted to Linux. The generic implementation -// does nothing. -// This code works only if the delayacct kernel feature is turned on. -// this is done by "sysctl kernel.task_delayacct=1". +// Package processmetrics provides a custom collector to export process-level metrics beyond what +// prometheus.ProcesssCollector offers. This implementation is restricted to Linux. The generic +// implementation does nothing. // -// In order to make a fair run-to-run comparison of these metrics, we must -// relate them to the actual CPU time that was *available* to the router. -// That is, the time that the process was either running, blocked, or sleeping, -// but not "runnable" (which in unix-ese implies *not* running). -// A custom collector in pkg/processmetrics exposes the running and runnable -// metrics directly from the scheduler. -// Possibly crude example of a query that accounts for available cpu: +// The metrics we add serve to estimate the available cpu time; that is, the amount of CPU that the +// scheduler granted to the process, independently of whether it ran with it or slept on it. The +// goal is to measure what the overall performance of the process would be if it was never +// preempted. For example, this could be expressed as some_output/available_cpu_time. +// +// At a given time, a given thread is either running, runnable, or sleeping. When running it +// consumes exactly one core. When runnable, it is being deprived of exactly one core (because Go +// does not create more runnable threads than there are cores, there is no other thread of that +// process that is receiving it.). So, for our accounting purposes, the total time that all the +// process's threads spend "runnable" is the total core*time that the process did not receive. The +// complement of that: the available_cpu_time is: num_cores * real_time - total_runnable_time. +// +// We expose only running and runnable times. Available time can be inferred more conveniently in +// prometheus queries depending on the desired unit. For example: +// * available_cpu_seconds_per_seconds = num_cores - rate(process_runnable_seconds_total) +// * available_machine_seconds_per_seconds = 1 - rate(process_runnable_seconds_total)/num_cores +// +// Example of a query for processed_pkts per available cpu seconds: // // rate(router_processed_pkts_total[1m]) // / on (instance, job) group_left () -// (1 - rate(process_runnable_seconds_total[1m])) +// (num_cores - rate(process_runnable_seconds_total[1m])) // -// This shows processed_packets per available cpu seconds, as opposed to -// real time. -// Possibly crude example of a query that only looks at cpu use efficiency; -// This shows processed_packets per consumed cpu seconds: +// Example of a query that only looks at on-cpu efficiency; // // rate(router_processed_pkts_total[1m]) // / on (instance, job) group_left () // (rate(process_running_seconds_total[1m])) // +// The effective number of cores is best obtained from the go runtime. However, no prometheus +// collector seems to expose it yet, so we surface it here for convenience and simplicity +// under the name go_maxprocs_threads. //go:build linux @@ -48,6 +56,7 @@ package processmetrics import ( "os" "path/filepath" + "runtime" "strconv" "syscall" @@ -58,24 +67,22 @@ import ( ) var ( - // These two metrics allows to infer the amount of CPU time that was available, used or not, - // to the process: - // wallClock time = runningTime + runnableTime + sleepingTime. - // availableCPU = runningTime + sleepingTime - // Therefore AvailbleTime = wallClockTime - runnableTime. - // runningTime should be the same as uTime+sTime reported in a variety of other ways, - // but when doing calculations, better use the two data from the same source. So, collect them - // both. runningTime = prometheus.NewDesc( "process_running_seconds_total", - "Time the process spend running since it started (all threads summed).", + "CPU time the process used (running state) since it started (all threads summed).", nil, nil, ) runnableTime = prometheus.NewDesc( "process_runnable_seconds_total", - "Time the process spend runnable (unscheduled) since it started (all threads summed).", + "CPU time the process was denied (runnable state) since it started (all threads summed).", + nil, nil, + ) + goCores = prometheus.NewDesc( + "go_sched_maxprocs_threads", + "The current runtime.GOMAXPROCS setting. The number of cores Go code uses simultaneously", nil, nil, ) + // This metric is introspective. It's trying to gauge if we're successful in collecting the // other two at a reasonable cost. tasklistUpdates = prometheus.NewDesc( @@ -172,6 +179,11 @@ func (c *procStatCollector) Collect(ch chan<- prometheus.Metric) { prometheus.CounterValue, float64(c.totalRunnable)/1000000000, // Report duration in SI ) + ch <- prometheus.MustNewConstMetric( + goCores, + prometheus.GaugeValue, + float64(runtime.GOMAXPROCS(-1)), + ) ch <- prometheus.MustNewConstMetric( tasklistUpdates, prometheus.CounterValue, diff --git a/router/config/config.go b/router/config/config.go index f3376a302..711bd73b6 100644 --- a/router/config/config.go +++ b/router/config/config.go @@ -1,5 +1,6 @@ // Copyright 2016 ETH Zurich // Copyright 2019 ETH Zurich, Anapaya Systems +// Copyright 2023 SCION Association // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -71,9 +72,15 @@ func (cfg *RouterConfig) Validate() error { } func (cfg *RouterConfig) InitDefaults() { + + // NumProcessors is the number of goroutines used to handle the processing queue. + // By default, there are as many as cores allowed by Go and other goroutines displace + // the packet processors sporadically. It may be either good or bad to create more + // processors (plus the other goroutines) than there are cores... experience will tell. if cfg.NumProcessors == 0 { cfg.NumProcessors = runtime.GOMAXPROCS(0) } + if cfg.NumSlowPathProcessors == 0 { cfg.NumSlowPathProcessors = 1 } diff --git a/tools/end2end/main.go b/tools/end2end/main.go index 1018f2247..8dff7dad6 100644 --- a/tools/end2end/main.go +++ b/tools/end2end/main.go @@ -1,5 +1,6 @@ // Copyright 2018 ETH Zurich // Copyright 2019 ETH Zurich, Anapaya Systems +// Copyright 2023 SCION Association // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,6 +14,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +// This is a general purpose client/server code for end2end tests. The client +// sends pings to the server until it receives at least one pong from the +// server or a given deadline is reached. The server responds to all pings and +// the client wait for a response before doing anything else. + package main import ( @@ -93,6 +99,7 @@ func realMain() int { return 1 } defer closeTracer() + if integration.Mode == integration.ModeServer { server{}.run() return 0 @@ -104,7 +111,7 @@ func realMain() int { func addFlags() { flag.Var(&remote, "remote", "(Mandatory for clients) address to connect to") flag.Var(timeout, "timeout", "The timeout for each attempt") - flag.BoolVar(&epic, "epic", false, "Enable EPIC.") + flag.BoolVar(&epic, "epic", false, "Enable EPIC") } func validateFlags() { @@ -119,6 +126,7 @@ func validateFlags() { integration.LogFatal("Invalid timeout provided", "timeout", timeout) } } + log.Info("Flags", "timeout", timeout, "epic", epic, "remote", remote) } type server struct{} @@ -226,7 +234,7 @@ func (s server) handlePing(conn snet.PacketConn) error { // reverse path rpath, ok := p.Path.(snet.RawPath) if !ok { - return serrors.New("unecpected path", "type", common.TypeOf(p.Path)) + return serrors.New("unexpected path", "type", common.TypeOf(p.Path)) } replypather := snet.DefaultReplyPather{} replyPath, err := replypather.ReplyPath(rpath) @@ -243,10 +251,9 @@ func (s server) handlePing(conn snet.PacketConn) error { } type client struct { - conn snet.PacketConn - port uint16 - sdConn daemon.Connector - + conn snet.PacketConn + port uint16 + sdConn daemon.Connector errorPaths map[snet.PathFingerprint]struct{} } @@ -278,6 +285,8 @@ func (c *client) run() int { return integration.AttemptRepeatedly("End2End", c.attemptRequest) } +// attemptRequest sends one ping packet and expect a pong. +// Returns true (which means "stop") *if both worked*. func (c *client) attemptRequest(n int) bool { timeoutCtx, cancel := context.WithTimeout(context.Background(), timeout.Duration) defer cancel() @@ -295,17 +304,19 @@ func (c *client) attemptRequest(n int) bool { } span, ctx = tracing.StartSpanFromCtx(ctx, "attempt.ping") defer span.Finish() + withTag := func(err error) error { + tracing.Error(span, err) + return err + } // Send ping if err := c.ping(ctx, n, path); err != nil { - tracing.Error(span, err) - logger.Error("Could not send packet", "err", err) + logger.Error("Could not send packet", "err", withTag(err)) return false } // Receive pong if err := c.pong(ctx); err != nil { - tracing.Error(span, err) - logger.Error("Error receiving pong", "err", err) + logger.Error("Error receiving pong", "err", withTag(err)) if path != nil { c.errorPaths[snet.Fingerprint(path)] = struct{}{} } diff --git a/tools/end2end_integration/BUILD.bazel b/tools/end2end_integration/BUILD.bazel index 31d5ae0f2..df5c957ea 100644 --- a/tools/end2end_integration/BUILD.bazel +++ b/tools/end2end_integration/BUILD.bazel @@ -19,6 +19,10 @@ go_library( scion_go_binary( name = "end2end_integration", + data = [ + "//tools/end2end", + "//tools/end2endblast", + ], embed = [":go_default_library"], visibility = ["//visibility:public"], ) diff --git a/tools/end2end_integration/main.go b/tools/end2end_integration/main.go index 757d25238..43efd2e09 100644 --- a/tools/end2end_integration/main.go +++ b/tools/end2end_integration/main.go @@ -1,4 +1,5 @@ // Copyright 2018 ETH Zurich, Anapaya Systems +// Copyright 2023 SCION Association // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -99,6 +100,7 @@ func realMain() int { log.Error("Error during tests", "err", err) return 1 } + return 0 } @@ -110,8 +112,9 @@ func addFlags() { flag.StringVar(&name, "name", "end2end_integration", "The name of the test that is running (default: end2end_integration)") flag.Var(timeout, "timeout", "The timeout for each attempt") - flag.StringVar(&subset, "subset", "all", "Subset of pairs to run (all|core#core|"+ - "noncore#localcore|noncore#core|noncore#noncore)") + flag.StringVar(&subset, "subset", "all", "Subset of pairs to run (all|#[#] "+ + " where =[|core|noncore] dst=[|core|noncore] and "+ + " is [localAS|remoteAS|localISD|remoteISD])") flag.IntVar(¶llelism, "parallelism", 1, "How many end2end tests run in parallel.") flag.StringVar(&features, "features", "", fmt.Sprintf("enable development features (%v)", feature.String(&feature.Default{}, "|"))) @@ -258,9 +261,22 @@ func runTests(in integration.Integration, pairs []integration.IAPair) error { clientResults <- err }(src, dsts) } + + // We started everything that could be started. So the best window for perf mertics + // opens somewhere around now. + metricsBegin := time.Now().Unix() errs = nil + end_reported := false for range groups { err := <-clientResults + if !end_reported { + end_reported = true + // The first client has finished. So the performance metrics have begun losing + // quality. + metricsEnd := time.Now().Unix() + // The test harness looks for this output. + fmt.Printf("metricsBegin: %d metricsEnd: %d\n", metricsBegin, metricsEnd) + } if err != nil { errs = append(errs, err) } @@ -295,21 +311,33 @@ func clientTemplate(progressSock string) integration.Cmd { } // getPairs returns the pairs to test according to the specified subset. +// The subset can be based on role, as follows: +// role1#role2[#local] selects all src:dst pairs matching such that src has role1 +// and dst has role2 (and NOT the other way around). If local[ISD|AS]/remote[ISD|AS] is specified +// then src and dst must/must-not be in the same ISD/AS +// +// This implies that IFF role1 == role2, then h1:h2 pairs are mirrored with h2:h1 and, unless +// remote[ISD/AS] is specified, h2:h2 and h1:h1. Not all combinations yield something useful... +// caveat emptor. func getPairs() ([]integration.IAPair, error) { pairs := integration.IAPairs(integration.DispAddr) if subset == "all" { return pairs, nil } parts := strings.Split(subset, "#") - if len(parts) != 2 { + switch len(parts) { + case 2: + return filter(parts[0], parts[1], "", pairs, integration.LoadedASList), nil + case 3: + return filter(parts[0], parts[1], parts[2], pairs, integration.LoadedASList), nil + default: return nil, serrors.New("Invalid subset", "subset", subset) } - return filter(parts[0], parts[1], pairs, integration.LoadedASList), nil } // filter returns the list of ASes that are part of the desired subset. func filter( - src, dst string, + src, dst, local string, pairs []integration.IAPair, ases *integration.ASList, ) []integration.IAPair { @@ -325,11 +353,21 @@ func filter( } } } + + // Selection based on role. for _, pair := range pairs { filter := !contains(ases, src != "noncore", pair.Src.IA) filter = filter || !contains(ases, dst != "noncore", pair.Dst.IA) - if dst == "localcore" { + switch local { + case "localISD": filter = filter || pair.Src.IA.ISD() != pair.Dst.IA.ISD() + case "remoteISD": + filter = filter || pair.Src.IA.ISD() == pair.Dst.IA.ISD() + case "localAS": + filter = filter || pair.Src.IA != pair.Dst.IA + case "remoteAS": + filter = filter || pair.Src.IA == pair.Dst.IA + default: } if !filter { res = append(res, pair) diff --git a/tools/end2endblast/BUILD.bazel b/tools/end2endblast/BUILD.bazel new file mode 100644 index 000000000..e89d3c45c --- /dev/null +++ b/tools/end2endblast/BUILD.bazel @@ -0,0 +1,30 @@ +load("//tools/lint:go.bzl", "go_library") +load("//:scion.bzl", "scion_go_binary") + +go_library( + name = "go_default_library", + srcs = ["main.go"], + importpath = "github.com/scionproto/scion/tools/end2endblast", + visibility = ["//visibility:private"], + deps = [ + "//pkg/addr:go_default_library", + "//pkg/daemon:go_default_library", + "//pkg/log:go_default_library", + "//pkg/private/common:go_default_library", + "//pkg/private/serrors:go_default_library", + "//pkg/private/util:go_default_library", + "//pkg/snet:go_default_library", + "//pkg/snet/metrics:go_default_library", + "//pkg/snet/path:go_default_library", + "//pkg/sock/reliable:go_default_library", + "//private/topology:go_default_library", + "//tools/integration:go_default_library", + "//tools/integration/integrationlib:go_default_library", + ], +) + +scion_go_binary( + name = "end2endblast", + embed = [":go_default_library"], + visibility = ["//visibility:public"], +) diff --git a/tools/end2endblast/main.go b/tools/end2endblast/main.go new file mode 100644 index 000000000..74d04ef85 --- /dev/null +++ b/tools/end2endblast/main.go @@ -0,0 +1,459 @@ +// Copyright 2023 SCION Association +// +// 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. + +// This is a client/server code for use by end2end tests. This one plays +// a variant of ping-pong where the client to send back-to-back pings to the +// server until the sending fails or some deadline was reached. In this case +// the client isn't waiting for responses. The client checks at the end +// whether at least one response has been received. The server responds rarely. + +package main + +import ( + "context" + "encoding/json" + "errors" + "flag" + "fmt" + "net" + "net/netip" + "os" + "time" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/daemon" + "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/private/common" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/private/util" + "github.com/scionproto/scion/pkg/snet" + "github.com/scionproto/scion/pkg/snet/metrics" + snetpath "github.com/scionproto/scion/pkg/snet/path" + "github.com/scionproto/scion/pkg/sock/reliable" + "github.com/scionproto/scion/private/topology" + libint "github.com/scionproto/scion/tools/integration" + integration "github.com/scionproto/scion/tools/integration/integrationlib" +) + +const ( + ping = "ping" + pong = "pong" +) + +type Ping struct { + Server addr.IA `json:"server"` + Message string `json:"message"` +} + +type Pong struct { + Client addr.IA `json:"client"` + Server addr.IA `json:"server"` + Message string `json:"message"` +} + +var ( + remote snet.UDPAddr + timeout = &util.DurWrap{Duration: 90 * time.Second} + scionPacketConnMetrics = metrics.NewSCIONPacketConnMetrics() + scmpErrorsCounter = scionPacketConnMetrics.SCMPErrors + epic bool +) + +func main() { + os.Exit(realMain()) +} + +func realMain() int { + defer log.HandlePanic() + defer log.Flush() + addFlags() + err := integration.Setup() + if err != nil { + log.Error("Parsing common flags failed", "err", err) + return 1 + } + validateFlags() + + if integration.Mode == integration.ModeServer { + (&server{}).run() + return 0 + } + c := client{} + return c.run() +} + +func addFlags() { + flag.Var(&remote, "remote", "(Mandatory for clients) address to connect to") + flag.Var(timeout, "timeout", "The timeout for completing the whole test") + flag.BoolVar(&epic, "epic", false, "Enable EPIC") +} + +func validateFlags() { + if integration.Mode == integration.ModeClient { + if remote.Host == nil { + integration.LogFatal("Missing remote address") + } + if remote.Host.Port == 0 { + integration.LogFatal("Invalid remote port", "remote port", remote.Host.Port) + } + if timeout.Duration == 0 { + integration.LogFatal("Invalid timeout provided", "timeout", timeout) + } + } + log.Info("Flags", "timeout", timeout, "epic", epic, "remote", remote) +} + +type server struct { + pongs uint8 // chosen to overflow. +} + +func (s *server) run() { + log.Info("Starting server", "isd_as", integration.Local.IA) + defer log.Info("Finished server", "isd_as", integration.Local.IA) + + sdConn := integration.SDConn() + defer sdConn.Close() + connFactory := &snet.DefaultPacketDispatcherService{ + Dispatcher: reliable.NewDispatcher(""), + SCMPHandler: snet.DefaultSCMPHandler{ + RevocationHandler: daemon.RevHandler{Connector: sdConn}, + SCMPErrors: scmpErrorsCounter, + }, + SCIONPacketConnMetrics: scionPacketConnMetrics, + } + + conn, port, err := connFactory.Register(context.Background(), integration.Local.IA, + integration.Local.Host, addr.SvcNone) + if err != nil { + integration.LogFatal("Error listening", "err", err) + } + defer conn.Close() + if len(os.Getenv(libint.GoIntegrationEnv)) > 0 { + // Needed for integration test ready signal. + fmt.Printf("Port=%d\n", port) + fmt.Printf("%s%s\n\n", libint.ReadySignal, integration.Local.IA) + } + + log.Info("Listening", "local", fmt.Sprintf("%v:%d", integration.Local.Host, port)) + + // Receive ping message + for { + if err := s.handlePing(conn); err != nil { + log.Error("Error handling ping", "err", err) + } + } +} + +func (s *server) handlePing(conn snet.PacketConn) error { + var p snet.Packet + var ov net.UDPAddr + if err := readFrom(conn, &p, &ov); err != nil { + return serrors.WrapStr("reading packet", err) + } + udp, ok := p.Payload.(snet.UDPPayload) + if !ok { + return serrors.New("unexpected payload received", + "source", p.Source, + "destination", p.Destination, + "type", common.TypeOf(p.Payload), + ) + } + var pld Ping + if err := json.Unmarshal(udp.Payload, &pld); err != nil { + return serrors.New("invalid payload contents", + "source", p.Source, + "destination", p.Destination, + "data", string(udp.Payload), + ) + } + + if pld.Message != ping || !pld.Server.Equal(integration.Local.IA) { + return serrors.New("unexpected data in payload", + "source", p.Source, + "destination", p.Destination, + "data", pld, + ) + } + + // In this game, we respond to 1/256 (~0.4%) of the pings. Just enough + // to prove that some pings were received, but not enough to distort + // performance data by mixing in traffic types. + if s.pongs++; s.pongs != 0 { + return nil + } + log.Info(fmt.Sprintf("Ping received from %s, sending pong.", p.Source)) + raw, err := json.Marshal(Pong{ + Client: p.Source.IA, + Server: integration.Local.IA, + Message: pong, + }) + if err != nil { + return serrors.WrapStr("packing pong", err) + } + + p.Destination, p.Source = p.Source, p.Destination + p.Payload = snet.UDPPayload{ + DstPort: udp.SrcPort, + SrcPort: udp.DstPort, + Payload: raw, + } + // reverse path + rpath, ok := p.Path.(snet.RawPath) + if !ok { + return serrors.New("unexpected path", "type", common.TypeOf(p.Path)) + } + replypather := snet.DefaultReplyPather{} + replyPath, err := replypather.ReplyPath(rpath) + if err != nil { + return serrors.WrapStr("creating reply path", err) + } + p.Path = replyPath + // Send pong + if err := conn.WriteTo(&p, &ov); err != nil { + return serrors.WrapStr("sending reply", err) + } + log.Info("Sent pong to", "client", p.Destination) + return nil +} + +type client struct { + conn snet.PacketConn + port uint16 + sdConn daemon.Connector + path snet.Path +} + +func (c *client) run() int { + pair := fmt.Sprintf("%s -> %s", integration.Local.IA, remote.IA) + log.Info("Starting", "pair", pair) + defer log.Info("Finished", "pair", pair) + defer integration.Done(integration.Local.IA, remote.IA) + connFactory := &snet.DefaultPacketDispatcherService{ + Dispatcher: reliable.NewDispatcher(""), + SCMPHandler: snet.DefaultSCMPHandler{ + RevocationHandler: daemon.RevHandler{Connector: integration.SDConn()}, + SCMPErrors: scmpErrorsCounter, + }, + SCIONPacketConnMetrics: scionPacketConnMetrics, + } + + var err error + c.conn, c.port, err = connFactory.Register(context.Background(), integration.Local.IA, + integration.Local.Host, addr.SvcNone) + if err != nil { + integration.LogFatal("Unable to listen", "err", err) + } + log.Info("Send on", "local", + fmt.Sprintf("%v,[%v]:%d", integration.Local.IA, integration.Local.Host.IP, c.port)) + c.sdConn = integration.SDConn() + defer c.sdConn.Close() + + // Drain pongs in the background + pongOut := make(chan int) + go func() { + defer log.HandlePanic() + + // The timeout extends over the entire test. When we don't need to drain any more + // we just cancel it. + ctx, cancel := context.WithTimeout(context.Background(), timeout.Duration) + defer cancel() + + // Drain pongs as long as we get them. We assume that failure means + // there are no more pongs. We want ro receive at least one pong. The + // rest doesn't matter. + allFailed := 1 + integration.RepeatUntilFail("End2EndBlast", func(n int) bool { + + if err := c.pong(ctx); err != nil { + // We should receive at least one, but this runs until pings stop + // coming, so there will always be one failure in the end. + return true // Stop. + } + allFailed = 0 + return false // Keep consuming pongs + }) + pongOut <- allFailed + }() + + // Same here, the timeout context lives on for the rest of the test (so we don't keep + // creating and discarding contexts). + ctx, cancel := context.WithTimeout(context.Background(), timeout.Duration) + defer cancel() + + // Get a path, then use it for all the repeats + p, err := c.getRemote(ctx) + if err != nil { + integration.LogFatal("Could not get remote", "err", err) + return 1 + } + c.path = p // struct fields cannot be assigned with := + + // We return a "number of failures". So 0 means everything is fine. + pingResult := integration.RepeatUntilFail("End2EndBlast", func(n int) bool { + // Send ping + if err := c.ping(ctx, n, c.path); err != nil { + logger := log.FromCtx(ctx) + logger.Error("Could not send packet", "err", err) + return true + } + + return false // Don't stop. Do it again! + }) + + // Stop drainPongs, so we're not stuck here for up to 10s. + c.conn.Close() + + pongResult := <-pongOut + if pongResult != 0 { + log.Info("Never got a single pong") + } + return pingResult + pongResult +} + +func (c *client) ping(ctx context.Context, n int, path snet.Path) error { + rawPing, err := json.Marshal(Ping{ + Server: remote.IA, + Message: ping, + }) + if err != nil { + return serrors.WrapStr("packing ping", err) + } + if err := c.conn.SetWriteDeadline(getDeadline(ctx)); err != nil { + return serrors.WrapStr("setting write deadline", err) + } + if remote.NextHop == nil { + remote.NextHop = &net.UDPAddr{ + IP: remote.Host.IP, + Port: topology.EndhostPort, + } + } + + remoteHostIP, ok := netip.AddrFromSlice(remote.Host.IP) + if !ok { + return serrors.New("invalid remote host IP", "ip", remote.Host.IP) + } + localHostIP, ok := netip.AddrFromSlice(integration.Local.Host.IP) + if !ok { + return serrors.New("invalid local host IP", "ip", integration.Local.Host.IP) + } + pkt := &snet.Packet{ + PacketInfo: snet.PacketInfo{ + Destination: snet.SCIONAddress{ + IA: remote.IA, + Host: addr.HostIP(remoteHostIP), + }, + Source: snet.SCIONAddress{ + IA: integration.Local.IA, + Host: addr.HostIP(localHostIP), + }, + Path: remote.Path, + Payload: snet.UDPPayload{ + SrcPort: c.port, + DstPort: uint16(remote.Host.Port), + Payload: rawPing, + }, + }, + } + if err := c.conn.WriteTo(pkt, remote.NextHop); err != nil { + return err + } + return nil +} + +func (c *client) getRemote(ctx context.Context) (snet.Path, error) { + if remote.IA.Equal(integration.Local.IA) { + remote.Path = snetpath.Empty{} + return nil, nil + } + paths, err := c.sdConn.Paths(ctx, remote.IA, integration.Local.IA, + daemon.PathReqFlags{Refresh: false}) + if err != nil { + return nil, serrors.WrapStr("requesting paths", err) + } + // Select first path + if len(paths) == 0 { + return nil, serrors.New("no path found") + } + path := paths[0] + + // Extract forwarding path from the SCION Daemon response. + // If the epic flag is set, try to use the EPIC path type header. + if epic { + scionPath, ok := path.Dataplane().(snetpath.SCION) + if !ok { + return nil, serrors.New("provided path must be of type scion") + } + epicPath, err := snetpath.NewEPICDataplanePath(scionPath, path.Metadata().EpicAuths) + if err != nil { + return nil, err + } + remote.Path = epicPath + } else { + remote.Path = path.Dataplane() + } + remote.NextHop = path.UnderlayNextHop() + return path, nil +} + +func (c *client) pong(ctx context.Context) error { + if err := c.conn.SetReadDeadline(getDeadline(ctx)); err != nil { + return serrors.WrapStr("setting read deadline", err) + } + var p snet.Packet + var ov net.UDPAddr + if err := readFrom(c.conn, &p, &ov); err != nil { + return serrors.WrapStr("reading packet", err) + } + + udp, ok := p.Payload.(snet.UDPPayload) + if !ok { + return serrors.New("unexpected payload received", "type", common.TypeOf(p.Payload)) + } + + var pld Pong + if err := json.Unmarshal(udp.Payload, &pld); err != nil { + return serrors.WrapStr("unpacking pong", err, "data", string(udp.Payload)) + } + + expected := Pong{ + Client: integration.Local.IA, + Server: remote.IA, + Message: pong, + } + if pld.Client != expected.Client || pld.Server != expected.Server || pld.Message != pong { + return serrors.New("unexpected contents received", "data", pld, "expected", expected) + } + return nil +} + +func getDeadline(ctx context.Context) time.Time { + dl, ok := ctx.Deadline() + if !ok { + integration.LogFatal("No deadline in context") + } + return dl +} + +func readFrom(conn snet.PacketConn, pkt *snet.Packet, ov *net.UDPAddr) error { + err := conn.ReadFrom(pkt, ov) + // Attach more context to error + var opErr *snet.OpError + if !(errors.As(err, &opErr) && opErr.RevInfo() != nil) { + return err + } + return serrors.WithCtx(err, + "isd_as", opErr.RevInfo().IA(), + "interface", opErr.RevInfo().IfID, + ) +} diff --git a/tools/integration/integrationlib/common.go b/tools/integration/integrationlib/common.go index 5a5090829..b215a97ae 100644 --- a/tools/integration/integrationlib/common.go +++ b/tools/integration/integrationlib/common.go @@ -1,5 +1,6 @@ // Copyright 2018 ETH Zurich // Copyright 2019 ETH Zurich, Anapaya Systems +// Copyright 2023 SCION Association // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -138,26 +139,39 @@ func SDConn() daemon.Connector { // AttemptFunc attempts a request repeatedly, receives the attempt number type AttemptFunc func(n int) bool -// AttemptRepeatedly runs attempt until it returns true or more than Attempts were executed. -// Between two attempts at least RetryTimeout time has to pass. +// AttemptRepeatedly runs attempt until it returns true (succeeded => stop) or more than Attempts +// were executed. Between two attempts at least RetryTimeout time has to pass. // Returns 0 on success, 1 on failure. func AttemptRepeatedly(name string, attempt AttemptFunc) int { - attempts := 0 - for { - attempts++ - if attempt(attempts) { - return 0 - } else if attempts < Attempts { + for attempts := 0; attempts < Attempts; attempts++ { + if attempts != 0 { log.Info("Retrying...") time.Sleep(integration.RetryTimeout) - continue } - log.Error(fmt.Sprintf("%s failed. No more attempts...", name)) - break + if attempt(attempts) { + return 0 + } } + log.Error(fmt.Sprintf("%s failed. No more attempts...", name)) return 1 } +// RepeatUntilFail runs doit() until it returns true (failed -> stop) or more than Attempts +// were executed. There is no delay nor logging between attempts. +// Returns 0 if all Attempts succeeded, 1 on failure. +// This is very similar to AttemptRepeatedly, but difference in failure/success behaviour +// justify a different function: parameter-based tweaks would be easily confusing. +func RepeatUntilFail(name string, doit AttemptFunc) int { + for attempts := 0; attempts < Attempts; attempts++ { + if doit(attempts) { + log.Error(fmt.Sprintf("%s failed...", name)) + return 1 + } + } + log.Info(fmt.Sprintf("%s completed. No more repeats...", name)) + return 0 +} + // Done informs the integration test that a test binary has finished. func Done(src, dst addr.IA) { if Progress == "" { diff --git a/tools/md/skipped b/tools/md/skipped index 5114feec2..ac3f13384 100644 --- a/tools/md/skipped +++ b/tools/md/skipped @@ -1,2 +1,3 @@ ^\./docker/_build/ ^\./licenses/data +^\./rules_openapi/tools/ diff --git a/topology/BUILD.bazel b/topology/BUILD.bazel index a76c5f070..2f2aa9ad9 100644 --- a/topology/BUILD.bazel +++ b/topology/BUILD.bazel @@ -11,5 +11,6 @@ exports_files( "tiny.topo", "tiny4.topo", "wide.topo", + "router_bm.topo", ], ) From c1e1abc9c94ef50dd497e37f698bd7e4913a1831 Mon Sep 17 00:00:00 2001 From: Markus Legner Date: Wed, 22 Nov 2023 20:17:13 +0100 Subject: [PATCH 084/255] daemon: fix docstring for latencies in protobuf file (#4443) Update the docstring to follow the semantics of negative means undefined. --- proto/daemon/v1/daemon.proto | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proto/daemon/v1/daemon.proto b/proto/daemon/v1/daemon.proto index e8b2758b2..3fb863200 100644 --- a/proto/daemon/v1/daemon.proto +++ b/proto/daemon/v1/daemon.proto @@ -74,7 +74,8 @@ message Path { // Latency lists the latencies between any two consecutive interfaces. // Entry i describes the latency between interface i and i+1. // Consequently, there are N-1 entries for N interfaces. - // A 0-value indicates that the AS did not announce a latency for this hop. + // A negative value indicates that the AS did not announce a latency for + // this hop. repeated google.protobuf.Duration latency = 6; // Bandwidth lists the bandwidth between any two consecutive interfaces, in // Kbit/s. From c890767bc6455cbd3786544543e169a069ed80cf Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Thu, 23 Nov 2023 11:01:12 +0100 Subject: [PATCH 085/255] scion.sh: block for child processes at shutdown (#4445) The `supervisorctl shutdown` command does not block for the supervisor or its child processes to terminate. This can occasionally lead to situations where SCION processes were still running after the `scion.sh stop` command returned. In the CI system, which immediately proceeds to bundle up the log files, this led to `tar` reporting an error that the log file was still being written to. Fixed by invoking `supervisorctl stop all`, which does block, to terminate all child processes before `shutdown`. --- scion.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scion.sh b/scion.sh index 7343c35d0..0f4851be1 100755 --- a/scion.sh +++ b/scion.sh @@ -113,7 +113,8 @@ stop_scion() { if is_docker_be; then ./tools/quiet ./tools/dc down else - ./tools/quiet tools/supervisor.sh shutdown + ./tools/quiet tools/supervisor.sh stop all # blocks until child processes are stopped + ./tools/quiet tools/supervisor.sh shutdown # shutdown does not block, but as children are already stopped, actual shutdown will be prompt too. run_teardown fi } From 799ed12888fc923ec7201e51527ef5c25210194a Mon Sep 17 00:00:00 2001 From: Markus Legner Date: Fri, 24 Nov 2023 12:39:41 +0100 Subject: [PATCH 086/255] processmetrics: explicit type conversion to support arm64 (#4446) --- pkg/private/processmetrics/processmetrics_linux.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/private/processmetrics/processmetrics_linux.go b/pkg/private/processmetrics/processmetrics_linux.go index 3132fa625..2953df24e 100644 --- a/pkg/private/processmetrics/processmetrics_linux.go +++ b/pkg/private/processmetrics/processmetrics_linux.go @@ -123,7 +123,8 @@ func (c *procStatCollector) updateStat() error { if err != nil { return err } - newCount := taskStat.Nlink - 2 + //nolint:unconvert // this is required for arm64 support + newCount := uint64(taskStat.Nlink - 2) if newCount != c.lastTaskCount { c.taskListUpdates++ c.myProcs, err = procfs.AllThreads(c.myPid) From a44d0bc2bc7d5b9369d40a77514e07ef83415e69 Mon Sep 17 00:00:00 2001 From: Markus Legner Date: Mon, 27 Nov 2023 16:25:20 +0100 Subject: [PATCH 087/255] bazel: update bazelisk and support arm64 (#4447) Bazel and bazilisk do support ARM64 by now. Lift the restriction on AMD64 and, while we're at it, update bazelisk to the latest version. --- tools/install_bazel | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tools/install_bazel b/tools/install_bazel index 1c8d38c43..3aef4e2bb 100755 --- a/tools/install_bazel +++ b/tools/install_bazel @@ -16,13 +16,27 @@ dl_install() { } MACH="$(uname -m)" -[ "$MACH" == "x86_64" ] || { echo "Error: bazel does not provide binaries for $MACH"; exit 1; } +case "$MACH" in + "x86_64") + ARCH=amd64 + BAZELISK_CKSUM=d28b588ac0916abd6bf02defb5433f6eddf7cba35ffa808eabb65a44aab226f7 + ;; + "aarch64") + ARCH=arm64 + BAZELISK_CKSUM=861a16ba9979613e70bd3d2f9d9ab5e3b59fe79471c5753acdc9c431ab6c9d94 + echo "Warning: ARM64 is not officially supported." + echo "You may encounter problems when building and running SCION components." + ;; + *) + echo "Error: bazel does not provide binaries for $MACH" + exit 1 + ;; +esac mkdir -p ~/.local/bin -BAZELISK_VER=v1.10.1 -BAZELISK_CKSUM=4cb534c52cdd47a6223d4596d530e7c9c785438ab3b0a49ff347e991c210b2cd -BAZELISK_FILE="bazelisk-linux-amd64" +BAZELISK_VER=v1.19.0 +BAZELISK_FILE="bazelisk-linux-${ARCH}" BAZELISK_URL=https://github.com/bazelbuild/bazelisk/releases/download/${BAZELISK_VER}/${BAZELISK_FILE} dl_install "$BAZELISK_URL" "$BAZELISK_CKSUM" ~/.local/bin/bazel From 237794a14f09915763be61c544e7577757c016d0 Mon Sep 17 00:00:00 2001 From: Markus Legner Date: Mon, 27 Nov 2023 18:31:00 +0100 Subject: [PATCH 088/255] build: allow building without scion-ci (#4449) The default target remains unchanged but is renamed to `build-dev`. The target `build` now only builds the main SCION services. --- .buildkite/pipeline.yml | 2 +- Makefile | 21 ++++++++++++--------- doc/dev/setup.rst | 3 +++ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 65ed0a203..96fd38b64 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -118,7 +118,7 @@ steps: - label: "E2E: default :docker: (ping)" command: - echo "--- build" - - make build docker-images + - make build-dev docker-images - echo "--- start topology" - ./scion.sh topology -d - ./scion.sh run diff --git a/Makefile b/Makefile index fc555c7e0..ad506aded 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,15 @@ -.PHONY: all antlr bazel clean docker-images gazelle go.mod licenses mocks protobuf scion-topo test test-integration write_all_source_files +.PHONY: all build build-dev antlr clean docker-images gazelle go.mod licenses mocks protobuf scion-topo test test-integration write_all_source_files -build: bazel +build-dev: + rm -f bin/* + bazel build //:scion //:scion-ci + tar -kxf bazel-bin/scion.tar -C bin + tar -kxf bazel-bin/scion-ci.tar -C bin + +build: + rm -f bin/* + bazel build //:scion + tar -kxf bazel-bin/scion.tar -C bin # all: performs the code-generation steps and then builds; the generated code # is git controlled, and therefore this is only necessary when changing the @@ -8,7 +17,7 @@ build: bazel # Use NOTPARALLEL to force correct order. # Note: From GNU make 4.4, this still allows building any other targets (e.g. lint) in parallel. .NOTPARALLEL: all -all: go_deps.bzl protobuf mocks gazelle build antlr write_all_source_files licenses +all: go_deps.bzl protobuf mocks gazelle build-dev antlr write_all_source_files licenses clean: bazel clean @@ -18,12 +27,6 @@ scrub: bazel clean --expunge rm -f bin/* -bazel: - rm -f bin/* - bazel build //:scion //:scion-ci - tar -kxf bazel-bin/scion.tar -C bin - tar -kxf bazel-bin/scion-ci.tar -C bin - test: bazel test --config=unit_all diff --git a/doc/dev/setup.rst b/doc/dev/setup.rst index dadeb2d69..4b6e5e7aa 100644 --- a/doc/dev/setup.rst +++ b/doc/dev/setup.rst @@ -72,6 +72,9 @@ Bazel make + .. hint:: This builds tools for tests in addition to the main SCION services (e.g., `end2end`); + if you don't require those, you can only build the SCION services by running ``make build``. + #. Finally, check that tests run correctly: .. code-block:: bash From 7fc08e4e8057451cddfe28b034e1744ac1cbe328 Mon Sep 17 00:00:00 2001 From: Martin Sustrik Date: Thu, 30 Nov 2023 09:14:55 +0100 Subject: [PATCH 089/255] prometheus: fix copying of metrics labels (#4450) When copying metric labels we assumed that `append` will always create a copy of the label array. This is not necessarily the case. In such case two metrics may end up with the same underlaying array of labels and change to one of them also overwrites the labels in the other one. --- pkg/metrics/prometheus.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/metrics/prometheus.go b/pkg/metrics/prometheus.go index 5667419b7..2f2632dbb 100644 --- a/pkg/metrics/prometheus.go +++ b/pkg/metrics/prometheus.go @@ -91,7 +91,9 @@ func (lvs labelValuesSlice) With(labelValues ...string) labelValuesSlice { if len(labelValues)%2 != 0 { labelValues = append(labelValues, "unknown") } - return append(lvs, labelValues...) + result := make(labelValuesSlice, len(lvs)) + copy(result, lvs) + return append(result, labelValues...) } // gauge implements Gauge, via a Prometheus GaugeVec. From 85b8a13a8e3abfc57ae66ff81f4dd2fdae5fe82e Mon Sep 17 00:00:00 2001 From: rohrerj <26304001+rohrerj@users.noreply.github.com> Date: Thu, 7 Dec 2023 09:06:13 +0100 Subject: [PATCH 090/255] daemon: error out when using drkey endpoints without configured drkey (#4453) I found a bug in the SCION daemon. If you create a SCION daemon connection and call one of the drkey endpoints without first setting the configuration value "drkey_level2_db.Connection" to something meaningful, the SCION daemon will encounter an error like that and crash: ``` panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0xb82d33] ``` This bug can easily be reproduced by running a code snippet like this for a SCION daemon that has no drkey configured: ``` sd, _ := daemon.NewService(daemonAddr).Connect(ctx) sd.DRKeyGetASHostKey(ctx, drkey.ASHostMeta{}) ``` The problem is that in the file "daemon/internal/servers/grpc.go", when the drkey endpoints are called, DaemonServer.DRKeyClient is nil if it is not configured as described above. Fixed by explicitly checking whether DRKey is available and erroring out if it is not. --- daemon/internal/servers/grpc.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/daemon/internal/servers/grpc.go b/daemon/internal/servers/grpc.go index b9e7af48f..dd2cb43bc 100644 --- a/daemon/internal/servers/grpc.go +++ b/daemon/internal/servers/grpc.go @@ -356,6 +356,9 @@ func (s *DaemonServer) DRKeyASHost( req *pb_daemon.DRKeyASHostRequest, ) (*pb_daemon.DRKeyASHostResponse, error) { + if s.DRKeyClient == nil { + return nil, serrors.New("DRKey is not available") + } meta, err := requestToASHostMeta(req) if err != nil { return nil, serrors.WrapStr("parsing protobuf ASHostReq", err) @@ -378,6 +381,9 @@ func (s *DaemonServer) DRKeyHostAS( req *pb_daemon.DRKeyHostASRequest, ) (*pb_daemon.DRKeyHostASResponse, error) { + if s.DRKeyClient == nil { + return nil, serrors.New("DRKey is not available") + } meta, err := requestToHostASMeta(req) if err != nil { return nil, serrors.WrapStr("parsing protobuf HostASReq", err) @@ -400,6 +406,9 @@ func (s *DaemonServer) DRKeyHostHost( req *pb_daemon.DRKeyHostHostRequest, ) (*pb_daemon.DRKeyHostHostResponse, error) { + if s.DRKeyClient == nil { + return nil, serrors.New("DRKey is not available") + } meta, err := requestToHostHostMeta(req) if err != nil { return nil, serrors.WrapStr("parsing protobuf HostHostReq", err) From b4e65a6e3189a37d658cc56f5be4e9403305d45d Mon Sep 17 00:00:00 2001 From: Lukas Vogel Date: Thu, 7 Dec 2023 09:31:09 +0100 Subject: [PATCH 091/255] pkg/log: fix panic when using custom Logger (#4452) log.FromCtx could panic if a custom Logger was used and a span was present in the context. This commit allows the custom logger to implement the `WithOptions(...zap.Option) Logger` method so that the CallerSkip can still be applied. In case the logger can't be casted to anything the caller skip is not applied, but we also don't panic anymore. --- pkg/log/context.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pkg/log/context.go b/pkg/log/context.go index 32b949390..d7c0813c8 100644 --- a/pkg/log/context.go +++ b/pkg/log/context.go @@ -65,8 +65,21 @@ func WithLabels(ctx context.Context, labels ...interface{}) (context.Context, Lo func attachSpan(ctx context.Context, l Logger) Logger { if span := opentracing.SpanFromContext(ctx); span != nil { + if optioner, ok := l.(interface{ WithOptions(...zap.Option) Logger }); ok { + return Span{ + Logger: optioner.WithOptions(zap.AddCallerSkip(1)), + Span: span, + } + } + if il, ok := l.(*logger); ok { + return Span{ + Logger: &logger{logger: il.logger.WithOptions(zap.AddCallerSkip(1))}, + Span: span, + } + } + // Pessimistic fallback, we don't have access to the underlying zap logger: return Span{ - Logger: &logger{logger: l.(*logger).logger.WithOptions(zap.AddCallerSkip(1))}, + Logger: l, Span: span, } } From d9c6c00b3d6036f47eda03a6b546cd8493298b6c Mon Sep 17 00:00:00 2001 From: jiceatscion <139873336+jiceatscion@users.noreply.github.com> Date: Thu, 7 Dec 2023 09:52:26 +0100 Subject: [PATCH 092/255] testing: an improved router benchmark that only runs one router (#4444) This is an alternative to router_benchmark and meant to eventually replace it. It's main feature is that it only runs a single router. As a result it's measured performance is far less dependent on the number of cores available on the test system. It is heavily inspired by the braccept test, in that: * it relies on the test harness to create an isolated network and veth interfaces to connect the test driver to the router. * it manufactures packets that are fed directly into the router's interfaces and it optionally captures packets for verification in the same manner. * it assumes a custom topology and cannot be usefully run on any other topology. It differs from braccept in that: * It does far less verification of the forwarded packets (it's braccept's job to do that). * It is considerably simplified, mainly because of the lighter verifications. * It relies on a simple address-assignment scheme so code maintainers don't have to keep tens of addresses in mind. * It does not assume that the router runs in a container network; it could also talk to a real router if given the names and mac addresses of the relevant interfaces. The test harness (or the user) is responsible for supplying the interface names and mac addresses to the test driver. * It does not require the test harness (or the user) to have any understanding of the topology (only to configure the router with it). The specifics of the captive network to be configured are supplied by the test driver. * The test harness doesn't need the "pause" container anymore. The similarity between this and braccept means that, in the future, we could re-converge them. Notably, the benefits of the simple addressing scheme would make the braccept test cases easier to maintain or expand. Collateral: the go version required was bumped to 1.21 Fixes #4442 --- acceptance/common/docker.py | 2 +- acceptance/router_benchmark/test.py | 2 +- acceptance/router_newbenchmark/BUILD.bazel | 28 ++ .../router_newbenchmark/brload/BUILD.bazel | 27 ++ acceptance/router_newbenchmark/brload/main.go | 316 +++++++++++++++++ .../router_newbenchmark/cases/BUILD.bazel | 29 ++ .../router_newbenchmark/cases/br_transit.go | 144 ++++++++ acceptance/router_newbenchmark/cases/in.go | 131 +++++++ .../router_newbenchmark/cases/in_transit.go | 144 ++++++++ acceptance/router_newbenchmark/cases/out.go | 133 +++++++ .../router_newbenchmark/cases/out_transit.go | 145 ++++++++ acceptance/router_newbenchmark/cases/topo.go | 236 +++++++++++++ acceptance/router_newbenchmark/conf/br.toml | 14 + .../router_newbenchmark/conf/keys/master0.key | 1 + .../router_newbenchmark/conf/keys/master1.key | 1 + .../router_newbenchmark/conf/prometheus.yml | 10 + .../router_newbenchmark/conf/topology.json | 46 +++ acceptance/router_newbenchmark/test.py | 331 ++++++++++++++++++ go.mod | 2 +- go.sum | 23 ++ router/connector.go | 2 +- 21 files changed, 1763 insertions(+), 4 deletions(-) create mode 100644 acceptance/router_newbenchmark/BUILD.bazel create mode 100644 acceptance/router_newbenchmark/brload/BUILD.bazel create mode 100644 acceptance/router_newbenchmark/brload/main.go create mode 100644 acceptance/router_newbenchmark/cases/BUILD.bazel create mode 100644 acceptance/router_newbenchmark/cases/br_transit.go create mode 100644 acceptance/router_newbenchmark/cases/in.go create mode 100644 acceptance/router_newbenchmark/cases/in_transit.go create mode 100644 acceptance/router_newbenchmark/cases/out.go create mode 100644 acceptance/router_newbenchmark/cases/out_transit.go create mode 100644 acceptance/router_newbenchmark/cases/topo.go create mode 100644 acceptance/router_newbenchmark/conf/br.toml create mode 100644 acceptance/router_newbenchmark/conf/keys/master0.key create mode 100644 acceptance/router_newbenchmark/conf/keys/master1.key create mode 100644 acceptance/router_newbenchmark/conf/prometheus.yml create mode 100644 acceptance/router_newbenchmark/conf/topology.json create mode 100644 acceptance/router_newbenchmark/test.py diff --git a/acceptance/common/docker.py b/acceptance/common/docker.py index 0af9a69bc..c6f56fb2c 100644 --- a/acceptance/common/docker.py +++ b/acceptance/common/docker.py @@ -197,7 +197,7 @@ def assert_no_networks(writer=None): writer.write("Docker networking assertions are OFF\n") return - allowed_nets = ['bridge', 'host', 'none'] + allowed_nets = ['bridge', 'host', 'none', 'benchmark'] unexpected_nets = [] for net in _get_networks(): if net.name not in allowed_nets: diff --git a/acceptance/router_benchmark/test.py b/acceptance/router_benchmark/test.py index 2049d9eea..428b58f71 100755 --- a/acceptance/router_benchmark/test.py +++ b/acceptance/router_benchmark/test.py @@ -141,7 +141,7 @@ def _run(self): "-name", "router_benchmark", "-cmd", "./bin/end2endblast", "-attempts", 1500000, - "-timeout", "120s", # Timeout is for all attempts together + "-timeout", "180s", # Timeout is for all attempts together "-parallelism", 100, "-subset", "noncore#core#remoteISD" ].run_tee() diff --git a/acceptance/router_newbenchmark/BUILD.bazel b/acceptance/router_newbenchmark/BUILD.bazel new file mode 100644 index 000000000..1a93da037 --- /dev/null +++ b/acceptance/router_newbenchmark/BUILD.bazel @@ -0,0 +1,28 @@ +load("//acceptance/common:raw.bzl", "raw_test") + +exports_files([ + "conf", + "test.py", +]) + +args = [ + "--executable", + "brload:$(location //acceptance/router_newbenchmark/brload:brload)", + "--container-loader=posix-router:latest#$(location //docker:posix_router)", +] + +data = [ + ":conf", + "//docker:posix_router", + "//acceptance/router_newbenchmark/brload:brload", +] + +raw_test( + name = "test", + src = "test.py", + args = args, + data = data, + homedir = "$(rootpath //docker:posix_router)", + # This test uses sudo and accesses /var/run/netns. + local = True, +) diff --git a/acceptance/router_newbenchmark/brload/BUILD.bazel b/acceptance/router_newbenchmark/brload/BUILD.bazel new file mode 100644 index 000000000..e475b8b68 --- /dev/null +++ b/acceptance/router_newbenchmark/brload/BUILD.bazel @@ -0,0 +1,27 @@ +load("//tools/lint:go.bzl", "go_library") +load("//:scion.bzl", "scion_go_binary") + +go_library( + name = "go_default_library", + srcs = ["main.go"], + importpath = "github.com/scionproto/scion/acceptance/router_newbenchmark/brload", + visibility = ["//visibility:private"], + deps = [ + "//acceptance/router_newbenchmark/cases:go_default_library", + "//pkg/log:go_default_library", + "//pkg/private/serrors:go_default_library", + "//pkg/scrypto:go_default_library", + "//pkg/slayers:go_default_library", + "//private/keyconf:go_default_library", + "@com_github_google_gopacket//:go_default_library", + "@com_github_google_gopacket//afpacket:go_default_library", + "@com_github_google_gopacket//layers:go_default_library", + "@com_github_spf13_cobra//:go_default_library", + ], +) + +scion_go_binary( + name = "brload", + embed = [":go_default_library"], + visibility = ["//visibility:public"], +) diff --git a/acceptance/router_newbenchmark/brload/main.go b/acceptance/router_newbenchmark/brload/main.go new file mode 100644 index 000000000..40e50cfbf --- /dev/null +++ b/acceptance/router_newbenchmark/brload/main.go @@ -0,0 +1,316 @@ +// Copyright 2023 SCION Association +// +// 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 main + +import ( + "errors" + "fmt" + "hash" + "net" + "os" + "path/filepath" + "reflect" + "strings" + "time" + + "github.com/google/gopacket" + "github.com/google/gopacket/afpacket" + "github.com/google/gopacket/layers" + "github.com/spf13/cobra" + + "github.com/scionproto/scion/acceptance/router_newbenchmark/cases" + "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/scrypto" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/private/keyconf" +) + +type Case func(payload string, mac hash.Hash, numDistinct int) (string, string, [][]byte) + +type caseChoice string + +func (c *caseChoice) String() string { + return string(*c) +} + +func (c *caseChoice) Set(v string) error { + _, ok := allCases[v] + if !ok { + return errors.New("No such case") + } + *c = caseChoice(v) + return nil +} + +func (c *caseChoice) Type() string { + return "string enum" +} + +func (c *caseChoice) Allowed() string { + return fmt.Sprintf("One of: %v", reflect.ValueOf(allCases).MapKeys()) +} + +var ( + allCases = map[string]Case{ + "in": cases.In, + "out": cases.Out, + "in_transit": cases.InTransit, + "out_transit": cases.OutTransit, + "br_transit": cases.BrTransit, + } + logConsole string + dir string + numPackets int + numStreams int + caseToRun caseChoice + interfaces []string +) + +func main() { + rootCmd := &cobra.Command{ + Use: "brload", + Short: "Generates traffic into a specific router of a specific topology", + } + intfCmd := &cobra.Command{ + Use: "show-interfaces", + Short: "Provides a terse list of the interfaces that this test requires", + Run: func(cmd *cobra.Command, args []string) { + os.Exit(showInterfaces(cmd)) + }, + } + runCmd := &cobra.Command{ + Use: "run", + Short: "Executes the test", + Run: func(cmd *cobra.Command, args []string) { + os.Exit(run(cmd)) + }, + } + runCmd.Flags().IntVar(&numPackets, "num-packets", 10, "Number of packets to send") + runCmd.Flags().IntVar(&numStreams, "num-streams", 4, + "Number of independent streams (flowID) to use") + runCmd.Flags().StringVar(&logConsole, "log.console", "error", + "Console logging level: debug|info|error|etc.") + runCmd.Flags().StringVar(&dir, "artifacts", "", "Artifacts directory") + runCmd.Flags().Var(&caseToRun, "case", "Case to run. "+caseToRun.Allowed()) + runCmd.Flags().StringArrayVar(&interfaces, "interface", []string{}, + `label=host_interface,mac,peer_mac where: + host_interface: use this to exchange traffic with interface