From d654196d0d1f158929d4915780e3c2810026e765 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Tue, 29 Aug 2023 19:18:27 +0000 Subject: [PATCH 1/2] Fix ResolveImageConfig to evaluate source policy Backport 330cf7ae7d9ac983432ab13f8bc9e7d4aff75695 to 0.11 branch This is not a clean cherry-pick due to lots of other interspersed changes (and this change really has to touch code all up and down the stack). Original commit message: Before this change, ResolveImageConfig was unaware of source policies. This means that: 1. Images for denied sources may be resolved 2. Image configs may get pulled for sources that are later converted to a different image The update makes it so the image resolver first runs a given ref through the source policy and uses any mutated ref for the actual resolve (instead of the original ref). It also returns the mutated ref so it can be used correctly by the frontend (e.g. don't want to do llb.Image(oldRef@resolvedDigest)). Signed-off-by: Brian Goff --- client/client_test.go | 101 +++- client/llb/imagemetaresolver/resolver.go | 13 +- client/llb/resolver.go | 5 +- client/llb/resolver_test.go | 6 +- client/llb/source.go | 8 +- frontend/attestations/sbom/sbom.go | 2 +- frontend/dockerfile/dockerfile2llb/convert.go | 17 +- frontend/frontend.go | 2 +- frontend/gateway/client/client.go | 2 +- frontend/gateway/gateway.go | 12 +- frontend/gateway/grpcclient/client.go | 27 +- frontend/gateway/pb/gateway.pb.go | 438 +++++++++++------- frontend/gateway/pb/gateway.proto | 2 + solver/llbsolver/bridge.go | 15 +- solver/llbsolver/provenance.go | 8 +- source/containerimage/pull.go | 13 +- sourcepolicy/engine.go | 17 +- util/imageutil/config.go | 70 ++- worker/base/worker.go | 2 +- worker/worker.go | 2 +- 20 files changed, 514 insertions(+), 248 deletions(-) diff --git a/client/client_test.go b/client/client_test.go index 3ac3b65b9bfd..be84a4ef1130 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -49,7 +49,6 @@ import ( "github.com/moby/buildkit/solver/result" "github.com/moby/buildkit/sourcepolicy" sourcepolicypb "github.com/moby/buildkit/sourcepolicy/pb" - spb "github.com/moby/buildkit/sourcepolicy/pb" "github.com/moby/buildkit/util/attestation" binfotypes "github.com/moby/buildkit/util/buildinfo/types" "github.com/moby/buildkit/util/contentutil" @@ -2601,7 +2600,7 @@ func testSourceDateEpochClamp(t *testing.T, sb integration.Sandbox) { var bboxConfig []byte _, err = c.Build(sb.Context(), SolveOpt{}, "", func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { - _, bboxConfig, err = c.ResolveImageConfig(ctx, "docker.io/library/busybox:latest", llb.ResolveImageConfigOpt{}) + _, _, bboxConfig, err = c.ResolveImageConfig(ctx, "docker.io/library/busybox:latest", llb.ResolveImageConfigOpt{}) if err != nil { return nil, err } @@ -8999,32 +8998,88 @@ func testSourcePolicy(t *testing.T, sb integration.Sandbox) { } t.Run("Frontend policies", func(t *testing.T) { - denied := "https://raw.githubusercontent.com/moby/buildkit/v0.10.1/README.md" - frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { - st := llb.Image("busybox:1.34.1-uclibc").File( - llb.Copy(llb.HTTP(denied), - "README.md", "README.md")) - def, err := st.Marshal(sb.Context()) - if err != nil { - return nil, err + t.Run("deny http", func(t *testing.T) { + denied := "https://raw.githubusercontent.com/moby/buildkit/v0.10.1/README.md" + frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { + st := llb.Image("busybox:1.34.1-uclibc").File( + llb.Copy(llb.HTTP(denied), + "README.md", "README.md")) + def, err := st.Marshal(sb.Context()) + if err != nil { + return nil, err + } + return c.Solve(ctx, gateway.SolveRequest{ + Definition: def.ToPB(), + SourcePolicies: []*sourcepolicypb.Policy{{ + Rules: []*sourcepolicypb.Rule{ + { + Action: sourcepolicypb.PolicyAction_DENY, + Selector: &sourcepolicypb.Selector{ + Identifier: denied, + }, + }, + }, + }}, + }) } - return c.Solve(ctx, gateway.SolveRequest{ - Definition: def.ToPB(), - SourcePolicies: []*spb.Policy{{ - Rules: []*spb.Rule{ - { - Action: spb.PolicyAction_DENY, - Selector: &spb.Selector{ - Identifier: denied, + + _, err = c.Build(sb.Context(), SolveOpt{}, "", frontend, nil) + require.ErrorContains(t, err, sourcepolicy.ErrSourceDenied.Error()) + }) + t.Run("resolve image config", func(t *testing.T) { + frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { + const ( + origRef = "docker.io/library/busybox:1.34.1-uclibc" + updatedRef = "docker.io/library/busybox:latest" + ) + pol := []*sourcepolicypb.Policy{ + { + Rules: []*sourcepolicypb.Rule{ + { + Action: sourcepolicypb.PolicyAction_DENY, + Selector: &sourcepolicypb.Selector{ + Identifier: "*", + }, + }, + { + Action: sourcepolicypb.PolicyAction_ALLOW, + Selector: &sourcepolicypb.Selector{ + Identifier: "docker-image://" + updatedRef + "*", + }, + }, + { + Action: sourcepolicypb.PolicyAction_CONVERT, + Selector: &sourcepolicypb.Selector{ + Identifier: "docker-image://" + origRef, + }, + Updates: &sourcepolicypb.Update{ + Identifier: "docker-image://" + updatedRef, + }, }, }, }, - }}, - }) - } + } - _, err = c.Build(sb.Context(), SolveOpt{}, "", frontend, nil) - require.ErrorContains(t, err, sourcepolicy.ErrSourceDenied.Error()) + ref, dgst, _, err := c.ResolveImageConfig(ctx, origRef, llb.ResolveImageConfigOpt{ + SourcePolicies: pol, + }) + if err != nil { + return nil, err + } + require.Equal(t, updatedRef, ref) + st := llb.Image(ref + "@" + dgst.String()) + def, err := st.Marshal(sb.Context()) + if err != nil { + return nil, err + } + return c.Solve(ctx, gateway.SolveRequest{ + Definition: def.ToPB(), + SourcePolicies: pol, + }) + } + _, err = c.Build(sb.Context(), SolveOpt{}, "", frontend, nil) + require.NoError(t, err) + }) }) } diff --git a/client/llb/imagemetaresolver/resolver.go b/client/llb/imagemetaresolver/resolver.go index 6dd40b694385..76980f411c44 100644 --- a/client/llb/imagemetaresolver/resolver.go +++ b/client/llb/imagemetaresolver/resolver.go @@ -71,11 +71,12 @@ type imageMetaResolver struct { } type resolveResult struct { + ref string config []byte dgst digest.Digest } -func (imr *imageMetaResolver) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error) { +func (imr *imageMetaResolver) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (string, digest.Digest, []byte, error) { imr.locker.Lock(ref) defer imr.locker.Unlock(ref) @@ -87,16 +88,16 @@ func (imr *imageMetaResolver) ResolveImageConfig(ctx context.Context, ref string k := imr.key(ref, platform) if res, ok := imr.cache[k]; ok { - return res.dgst, res.config, nil + return res.ref, res.dgst, res.config, nil } - dgst, config, err := imageutil.Config(ctx, ref, imr.resolver, imr.buffer, nil, platform) + ref, dgst, config, err := imageutil.Config(ctx, ref, imr.resolver, imr.buffer, nil, platform, opt.SourcePolicies) if err != nil { - return "", nil, err + return "", "", nil, err } - imr.cache[k] = resolveResult{dgst: dgst, config: config} - return dgst, config, nil + imr.cache[k] = resolveResult{dgst: dgst, config: config, ref: ref} + return ref, dgst, config, nil } func (imr *imageMetaResolver) key(ref string, platform *ocispecs.Platform) string { diff --git a/client/llb/resolver.go b/client/llb/resolver.go index b3b9cdf751c7..02644f62c78b 100644 --- a/client/llb/resolver.go +++ b/client/llb/resolver.go @@ -3,6 +3,7 @@ package llb import ( "context" + spb "github.com/moby/buildkit/sourcepolicy/pb" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -31,7 +32,7 @@ func WithLayerLimit(l int) ImageOption { // ImageMetaResolver can resolve image config metadata from a reference type ImageMetaResolver interface { - ResolveImageConfig(ctx context.Context, ref string, opt ResolveImageConfigOpt) (digest.Digest, []byte, error) + ResolveImageConfig(ctx context.Context, ref string, opt ResolveImageConfigOpt) (string, digest.Digest, []byte, error) } type ResolverType int @@ -49,6 +50,8 @@ type ResolveImageConfigOpt struct { LogName string Store ResolveImageConfigOptStore + + SourcePolicies []*spb.Policy } type ResolveImageConfigOptStore struct { diff --git a/client/llb/resolver_test.go b/client/llb/resolver_test.go index 9771ce1aaf6d..49aaf177b99d 100644 --- a/client/llb/resolver_test.go +++ b/client/llb/resolver_test.go @@ -74,7 +74,7 @@ type testResolver struct { platform string } -func (r *testResolver) ResolveImageConfig(ctx context.Context, ref string, opt ResolveImageConfigOpt) (digest.Digest, []byte, error) { +func (r *testResolver) ResolveImageConfig(ctx context.Context, ref string, opt ResolveImageConfigOpt) (string, digest.Digest, []byte, error) { var img struct { Config struct { Env []string `json:"Env,omitempty"` @@ -92,7 +92,7 @@ func (r *testResolver) ResolveImageConfig(ctx context.Context, ref string, opt R dt, err := json.Marshal(img) if err != nil { - return "", nil, errors.WithStack(err) + return "", "", nil, errors.WithStack(err) } - return r.digest, dt, nil + return ref, r.digest, dt, nil } diff --git a/client/llb/source.go b/client/llb/source.go index 27c8c1b617f2..1cd2a549832c 100644 --- a/client/llb/source.go +++ b/client/llb/source.go @@ -131,7 +131,7 @@ func Image(ref string, opts ...ImageOption) State { if p == nil { p = c.Platform } - _, dt, err := info.metaResolver.ResolveImageConfig(ctx, ref, ResolveImageConfigOpt{ + _, _, dt, err := info.metaResolver.ResolveImageConfig(ctx, ref, ResolveImageConfigOpt{ Platform: p, ResolveMode: info.resolveMode.String(), ResolverType: ResolverTypeRegistry, @@ -147,7 +147,7 @@ func Image(ref string, opts ...ImageOption) State { if p == nil { p = c.Platform } - dgst, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, ResolveImageConfigOpt{ + ref, dgst, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, ResolveImageConfigOpt{ Platform: p, ResolveMode: info.resolveMode.String(), ResolverType: ResolverTypeRegistry, @@ -155,6 +155,10 @@ func Image(ref string, opts ...ImageOption) State { if err != nil { return State{}, err } + r, err := reference.ParseNormalizedNamed(ref) + if err != nil { + return State{}, err + } if dgst != "" { r, err = reference.WithDigest(r, dgst) if err != nil { diff --git a/frontend/attestations/sbom/sbom.go b/frontend/attestations/sbom/sbom.go index 113797b2139c..4f2d32d141c1 100644 --- a/frontend/attestations/sbom/sbom.go +++ b/frontend/attestations/sbom/sbom.go @@ -38,7 +38,7 @@ func CreateSBOMScanner(ctx context.Context, resolver llb.ImageMetaResolver, scan return nil, nil } - _, dt, err := resolver.ResolveImageConfig(ctx, scanner, llb.ResolveImageConfigOpt{}) + scanner, _, dt, err := resolver.ResolveImageConfig(ctx, scanner, llb.ResolveImageConfigOpt{}) if err != nil { return nil, err } diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index 6476267e2d32..8b56ca0d9d87 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -430,15 +430,22 @@ func toDispatchState(ctx context.Context, dt []byte, opt ConvertOpt) (*dispatchS prefix += platforms.Format(*platform) + " " } prefix += "internal]" - dgst, dt, err := metaResolver.ResolveImageConfig(ctx, d.stage.BaseName, llb.ResolveImageConfigOpt{ - Platform: platform, - ResolveMode: opt.ImageResolveMode.String(), - LogName: fmt.Sprintf("%s load metadata for %s", prefix, d.stage.BaseName), - ResolverType: llb.ResolverTypeRegistry, + mutRef, dgst, dt, err := metaResolver.ResolveImageConfig(ctx, d.stage.BaseName, llb.ResolveImageConfigOpt{ + Platform: platform, + ResolveMode: opt.ImageResolveMode.String(), + LogName: fmt.Sprintf("%s load metadata for %s", prefix, d.stage.BaseName), + ResolverType: llb.ResolverTypeRegistry, + SourcePolicies: nil, }) if err != nil { return suggest.WrapError(errors.Wrap(err, origName), origName, append(allStageNames, commonImageNames()...), true) } + if ref.String() != mutRef { + ref, err = reference.ParseNormalizedNamed(mutRef) + if err != nil { + return errors.Wrapf(err, "failed to parse ref %q", mutRef) + } + } var img Image if err := json.Unmarshal(dt, &img); err != nil { return errors.Wrap(err, "failed to parse image config") diff --git a/frontend/frontend.go b/frontend/frontend.go index 024ac802045c..fb89a8414afa 100644 --- a/frontend/frontend.go +++ b/frontend/frontend.go @@ -22,7 +22,7 @@ type Frontend interface { type FrontendLLBBridge interface { Solve(ctx context.Context, req SolveRequest, sid string) (*Result, error) - ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error) + ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (string, digest.Digest, []byte, error) Warn(ctx context.Context, dgst digest.Digest, msg string, opts WarnOpts) error } diff --git a/frontend/gateway/client/client.go b/frontend/gateway/client/client.go index 7b6b9de132bc..c247c8340ff7 100644 --- a/frontend/gateway/client/client.go +++ b/frontend/gateway/client/client.go @@ -27,7 +27,7 @@ func NewResult() *Result { type Client interface { Solve(ctx context.Context, req SolveRequest) (*Result, error) - ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error) + ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (string, digest.Digest, []byte, error) BuildOpts() BuildOpts Inputs(ctx context.Context) (map[string]llb.State, error) NewContainer(ctx context.Context, req NewContainerRequest) (Container, error) diff --git a/frontend/gateway/gateway.go b/frontend/gateway/gateway.go index 79825d0b651a..ddb1c39423ca 100644 --- a/frontend/gateway/gateway.go +++ b/frontend/gateway/gateway.go @@ -142,10 +142,16 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten return nil, err } - dgst, config, err := llbBridge.ResolveImageConfig(ctx, reference.TagNameOnly(sourceRef).String(), llb.ResolveImageConfigOpt{}) + ref, dgst, config, err := llbBridge.ResolveImageConfig(ctx, reference.TagNameOnly(sourceRef).String(), llb.ResolveImageConfigOpt{}) if err != nil { return nil, err } + + sourceRef, err = reference.ParseNormalizedNamed(ref) + if err != nil { + return nil, err + } + mfstDigest = dgst if err := json.Unmarshal(config, &img); err != nil { @@ -540,7 +546,7 @@ func (lbf *llbBridgeForwarder) ResolveImageConfig(ctx context.Context, req *pb.R OSFeatures: p.OSFeatures, } } - dgst, dt, err := lbf.llbBridge.ResolveImageConfig(ctx, req.Ref, llb.ResolveImageConfigOpt{ + ref, dgst, dt, err := lbf.llbBridge.ResolveImageConfig(ctx, req.Ref, llb.ResolveImageConfigOpt{ ResolverType: llb.ResolverType(req.ResolverType), Platform: platform, ResolveMode: req.ResolveMode, @@ -549,11 +555,13 @@ func (lbf *llbBridgeForwarder) ResolveImageConfig(ctx context.Context, req *pb.R SessionID: req.SessionID, StoreID: req.StoreID, }, + SourcePolicies: req.SourcePolicies, }) if err != nil { return nil, err } return &pb.ResolveImageConfigResponse{ + Ref: ref, Digest: dgst, Config: dt, }, nil diff --git a/frontend/gateway/grpcclient/client.go b/frontend/gateway/grpcclient/client.go index 252617ffa047..9514a0163c24 100644 --- a/frontend/gateway/grpcclient/client.go +++ b/frontend/gateway/grpcclient/client.go @@ -478,7 +478,7 @@ func (c *grpcClient) Solve(ctx context.Context, creq client.SolveRequest) (res * return res, nil } -func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error) { +func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (string, digest.Digest, []byte, error) { var p *opspb.Platform if platform := opt.Platform; platform != nil { p = &opspb.Platform{ @@ -490,18 +490,25 @@ func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, opt llb } } resp, err := c.client.ResolveImageConfig(ctx, &pb.ResolveImageConfigRequest{ - ResolverType: int32(opt.ResolverType), - Ref: ref, - Platform: p, - ResolveMode: opt.ResolveMode, - LogName: opt.LogName, - SessionID: opt.Store.SessionID, - StoreID: opt.Store.StoreID, + ResolverType: int32(opt.ResolverType), + Ref: ref, + Platform: p, + ResolveMode: opt.ResolveMode, + LogName: opt.LogName, + SessionID: opt.Store.SessionID, + StoreID: opt.Store.StoreID, + SourcePolicies: opt.SourcePolicies, }) if err != nil { - return "", nil, err + return "", "", nil, err } - return resp.Digest, resp.Config, nil + newRef := resp.Ref + if newRef == "" { + // No ref returned, use the original one. + // This could occur if the version of buildkitd is too old. + newRef = ref + } + return newRef, resp.Digest, resp.Config, nil } func (c *grpcClient) BuildOpts() client.BuildOpts { diff --git a/frontend/gateway/pb/gateway.pb.go b/frontend/gateway/pb/gateway.pb.go index da36afdd140b..e914f9b24563 100644 --- a/frontend/gateway/pb/gateway.pb.go +++ b/frontend/gateway/pb/gateway.pb.go @@ -736,16 +736,17 @@ func (m *InputsResponse) GetDefinitions() map[string]*pb.Definition { } type ResolveImageConfigRequest struct { - Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` - Platform *pb.Platform `protobuf:"bytes,2,opt,name=Platform,proto3" json:"Platform,omitempty"` - ResolveMode string `protobuf:"bytes,3,opt,name=ResolveMode,proto3" json:"ResolveMode,omitempty"` - LogName string `protobuf:"bytes,4,opt,name=LogName,proto3" json:"LogName,omitempty"` - ResolverType int32 `protobuf:"varint,5,opt,name=ResolverType,proto3" json:"ResolverType,omitempty"` - SessionID string `protobuf:"bytes,6,opt,name=SessionID,proto3" json:"SessionID,omitempty"` - StoreID string `protobuf:"bytes,7,opt,name=StoreID,proto3" json:"StoreID,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` + Platform *pb.Platform `protobuf:"bytes,2,opt,name=Platform,proto3" json:"Platform,omitempty"` + ResolveMode string `protobuf:"bytes,3,opt,name=ResolveMode,proto3" json:"ResolveMode,omitempty"` + LogName string `protobuf:"bytes,4,opt,name=LogName,proto3" json:"LogName,omitempty"` + ResolverType int32 `protobuf:"varint,5,opt,name=ResolverType,proto3" json:"ResolverType,omitempty"` + SessionID string `protobuf:"bytes,6,opt,name=SessionID,proto3" json:"SessionID,omitempty"` + StoreID string `protobuf:"bytes,7,opt,name=StoreID,proto3" json:"StoreID,omitempty"` + SourcePolicies []*pb1.Policy `protobuf:"bytes,8,rep,name=SourcePolicies,proto3" json:"SourcePolicies,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ResolveImageConfigRequest) Reset() { *m = ResolveImageConfigRequest{} } @@ -830,9 +831,17 @@ func (m *ResolveImageConfigRequest) GetStoreID() string { return "" } +func (m *ResolveImageConfigRequest) GetSourcePolicies() []*pb1.Policy { + if m != nil { + return m.SourcePolicies + } + return nil +} + type ResolveImageConfigResponse struct { Digest github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=Digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"Digest"` Config []byte `protobuf:"bytes,2,opt,name=Config,proto3" json:"Config,omitempty"` + Ref string `protobuf:"bytes,3,opt,name=Ref,proto3" json:"Ref,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -878,6 +887,13 @@ func (m *ResolveImageConfigResponse) GetConfig() []byte { return nil } +func (m *ResolveImageConfigResponse) GetRef() string { + if m != nil { + return m.Ref + } + return "" +} + type SolveRequest struct { Definition *pb.Definition `protobuf:"bytes,1,opt,name=Definition,proto3" json:"Definition,omitempty"` Frontend string `protobuf:"bytes,2,opt,name=Frontend,proto3" json:"Frontend,omitempty"` @@ -2627,161 +2643,162 @@ func init() { func init() { proto.RegisterFile("gateway.proto", fileDescriptor_f1a937782ebbded5) } var fileDescriptor_f1a937782ebbded5 = []byte{ - // 2452 bytes of a gzipped FileDescriptorProto + // 2465 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x59, 0xcf, 0x6f, 0x1b, 0xc7, - 0xf5, 0xd7, 0x8a, 0x14, 0x25, 0x3d, 0x52, 0x14, 0x3d, 0x76, 0xf2, 0xa5, 0x17, 0x81, 0x23, 0xaf, + 0xf5, 0xd7, 0x8a, 0x14, 0x45, 0x3d, 0xfe, 0x10, 0x3d, 0x76, 0xf2, 0xa5, 0x17, 0x81, 0x23, 0xaf, 0x63, 0x45, 0x56, 0x9c, 0xa5, 0xbf, 0xb2, 0x0d, 0xb9, 0x76, 0xeb, 0xc4, 0xfa, 0x05, 0x29, 0x96, 0x6c, 0x76, 0xe4, 0xc2, 0x45, 0x90, 0x02, 0x5d, 0x71, 0x87, 0xf4, 0xd6, 0xab, 0xdd, 0xed, 0xee, - 0xd0, 0x32, 0x93, 0x4b, 0x7b, 0x28, 0x50, 0xe4, 0xd4, 0x53, 0x6f, 0x41, 0x81, 0x16, 0xe8, 0xb9, - 0xfd, 0x03, 0xda, 0x73, 0x80, 0x5e, 0x7a, 0xee, 0x21, 0x28, 0xfc, 0x0f, 0xf4, 0x56, 0xa0, 0xb7, - 0xe2, 0xcd, 0xcc, 0x92, 0xc3, 0x1f, 0x5a, 0x92, 0xf5, 0x89, 0x33, 0x6f, 0xde, 0x8f, 0x79, 0xef, - 0xcd, 0x7b, 0xf3, 0x99, 0x25, 0x2c, 0xb5, 0x1c, 0xce, 0xce, 0x9c, 0x8e, 0x1d, 0xc5, 0x21, 0x0f, - 0xc9, 0xe5, 0xd3, 0xf0, 0xa4, 0x63, 0x9f, 0xb4, 0x3d, 0xdf, 0x7d, 0xe9, 0x71, 0xfb, 0xd5, 0xff, - 0xdb, 0xcd, 0x38, 0x0c, 0x38, 0x0b, 0x5c, 0xf3, 0xe3, 0x96, 0xc7, 0x5f, 0xb4, 0x4f, 0xec, 0x46, - 0x78, 0x5a, 0x6b, 0x85, 0xad, 0xb0, 0x26, 0x24, 0x4e, 0xda, 0x4d, 0x31, 0x13, 0x13, 0x31, 0x92, - 0x9a, 0xcc, 0x8d, 0x41, 0xf6, 0x56, 0x18, 0xb6, 0x7c, 0xe6, 0x44, 0x5e, 0xa2, 0x86, 0xb5, 0x38, - 0x6a, 0xd4, 0x12, 0xee, 0xf0, 0x76, 0xa2, 0x64, 0x6e, 0x6a, 0x32, 0xb8, 0x91, 0x5a, 0xba, 0x91, - 0x5a, 0x12, 0xfa, 0xaf, 0x58, 0x5c, 0x8b, 0x4e, 0x6a, 0x61, 0x94, 0x72, 0xd7, 0xce, 0xe5, 0x76, - 0x22, 0xaf, 0xc6, 0x3b, 0x11, 0x4b, 0x6a, 0x67, 0x61, 0xfc, 0x92, 0xc5, 0x4a, 0xe0, 0xf6, 0xb9, - 0x02, 0x6d, 0xee, 0xf9, 0x28, 0xd5, 0x70, 0xa2, 0x04, 0x8d, 0xe0, 0xaf, 0x12, 0xd2, 0xdd, 0xe6, - 0x61, 0xe0, 0x25, 0xdc, 0xf3, 0x5a, 0x5e, 0xad, 0x99, 0x08, 0x19, 0x69, 0x05, 0x9d, 0x50, 0xec, - 0x77, 0x33, 0x5c, 0x68, 0xc7, 0x0d, 0x16, 0x85, 0xbe, 0xd7, 0xe8, 0xa0, 0x0d, 0x39, 0x92, 0x62, - 0xd6, 0xdf, 0xf2, 0x50, 0xa0, 0x2c, 0x69, 0xfb, 0x9c, 0xac, 0xc2, 0x52, 0xcc, 0x9a, 0x3b, 0x2c, - 0x8a, 0x59, 0xc3, 0xe1, 0xcc, 0xad, 0x1a, 0x2b, 0xc6, 0xda, 0xe2, 0xfe, 0x0c, 0xed, 0x27, 0x93, - 0x1f, 0x41, 0x39, 0x66, 0xcd, 0x44, 0x63, 0x9c, 0x5d, 0x31, 0xd6, 0x8a, 0x1b, 0x1f, 0xd9, 0xe7, - 0xe6, 0xd0, 0xa6, 0xac, 0x79, 0xe4, 0x44, 0x3d, 0x91, 0xfd, 0x19, 0x3a, 0xa0, 0x84, 0x6c, 0x40, - 0x2e, 0x66, 0xcd, 0x6a, 0x4e, 0xe8, 0xba, 0x92, 0xad, 0x6b, 0x7f, 0x86, 0x22, 0x33, 0xd9, 0x84, - 0x3c, 0x6a, 0xa9, 0xe6, 0x85, 0xd0, 0xd5, 0xb1, 0x1b, 0xd8, 0x9f, 0xa1, 0x42, 0x80, 0x3c, 0x86, - 0x85, 0x53, 0xc6, 0x1d, 0xd7, 0xe1, 0x4e, 0x15, 0x56, 0x72, 0x6b, 0xc5, 0x8d, 0x5a, 0xa6, 0x30, - 0x06, 0xc8, 0x3e, 0x52, 0x12, 0xbb, 0x01, 0x8f, 0x3b, 0xb4, 0xab, 0x80, 0x3c, 0x87, 0x92, 0xc3, - 0x39, 0xc3, 0x64, 0x78, 0x61, 0x90, 0x54, 0x4b, 0x42, 0xe1, 0xed, 0xf1, 0x0a, 0x1f, 0x69, 0x52, - 0x52, 0x69, 0x9f, 0x22, 0xf3, 0x01, 0x2c, 0xf5, 0xd9, 0x24, 0x15, 0xc8, 0xbd, 0x64, 0x1d, 0x99, - 0x18, 0x8a, 0x43, 0x72, 0x09, 0xe6, 0x5e, 0x39, 0x7e, 0x9b, 0x89, 0x1c, 0x94, 0xa8, 0x9c, 0xdc, - 0x9f, 0xbd, 0x67, 0x98, 0x2f, 0xe0, 0xc2, 0x90, 0xfe, 0x11, 0x0a, 0x7e, 0xa0, 0x2b, 0x28, 0x6e, - 0x7c, 0x98, 0xb1, 0x6b, 0x5d, 0x9d, 0x66, 0x69, 0x6b, 0x01, 0x0a, 0xb1, 0x70, 0xc8, 0xfa, 0xad, - 0x01, 0x95, 0xc1, 0x54, 0x93, 0x03, 0x95, 0x24, 0x43, 0x84, 0xe5, 0xee, 0x14, 0xa7, 0x04, 0x09, - 0x2a, 0x30, 0x42, 0x85, 0xb9, 0x09, 0x8b, 0x5d, 0xd2, 0xb8, 0x60, 0x2c, 0x6a, 0x5b, 0xb4, 0x36, - 0x21, 0x47, 0x59, 0x93, 0x94, 0x61, 0xd6, 0x53, 0xe7, 0x9a, 0xce, 0x7a, 0x2e, 0x59, 0x81, 0x9c, - 0xcb, 0x9a, 0xca, 0xf5, 0xb2, 0x1d, 0x9d, 0xd8, 0x3b, 0xac, 0xe9, 0x05, 0x1e, 0xba, 0x48, 0x71, - 0xc9, 0xfa, 0xbd, 0x81, 0xf5, 0x81, 0xdb, 0x22, 0x9f, 0xf4, 0xf9, 0x31, 0xfe, 0xb4, 0x0f, 0xed, - 0xfe, 0x79, 0xf6, 0xee, 0xef, 0xf4, 0x67, 0x62, 0x4c, 0x09, 0xe8, 0xde, 0xfd, 0x18, 0x4a, 0x7a, - 0x6e, 0xc8, 0x3e, 0x14, 0xb5, 0x73, 0xa4, 0x36, 0xbc, 0x3a, 0x59, 0x66, 0xa9, 0x2e, 0x6a, 0xfd, - 0x31, 0x07, 0x45, 0x6d, 0x91, 0x3c, 0x84, 0xfc, 0x4b, 0x2f, 0x90, 0x21, 0x2c, 0x6f, 0xac, 0x4f, - 0xa6, 0xf2, 0xb1, 0x17, 0xb8, 0x54, 0xc8, 0x91, 0xba, 0x56, 0x77, 0xb3, 0x62, 0x5b, 0x77, 0x26, - 0xd3, 0x71, 0x6e, 0xf1, 0xdd, 0x9a, 0xa2, 0x6d, 0xc8, 0xa6, 0x41, 0x20, 0x1f, 0x39, 0xfc, 0x85, - 0x68, 0x1a, 0x8b, 0x54, 0x8c, 0xc9, 0x2d, 0xb8, 0xe8, 0x05, 0xcf, 0x42, 0x1e, 0xd6, 0x63, 0xe6, - 0x7a, 0x78, 0xf8, 0x9e, 0x75, 0x22, 0x56, 0x9d, 0x13, 0x2c, 0xa3, 0x96, 0x48, 0x1d, 0xca, 0x92, - 0x7c, 0xdc, 0x3e, 0xf9, 0x19, 0x6b, 0xf0, 0xa4, 0x5a, 0x10, 0xfe, 0xac, 0x65, 0x6c, 0xe1, 0x40, - 0x17, 0xa0, 0x03, 0xf2, 0x6f, 0x55, 0xed, 0xd6, 0x9f, 0x0d, 0x58, 0xea, 0x53, 0x4f, 0x3e, 0xed, - 0x4b, 0xd5, 0xcd, 0x49, 0xb7, 0xa5, 0x25, 0xeb, 0x33, 0x28, 0xb8, 0x5e, 0x8b, 0x25, 0x5c, 0xa4, - 0x6a, 0x71, 0x6b, 0xe3, 0xdb, 0xef, 0xde, 0x9f, 0xf9, 0xc7, 0x77, 0xef, 0xaf, 0x6b, 0x57, 0x4d, - 0x18, 0xb1, 0xa0, 0x11, 0x06, 0xdc, 0xf1, 0x02, 0x16, 0xe3, 0x05, 0xfb, 0xb1, 0x14, 0xb1, 0x77, - 0xc4, 0x0f, 0x55, 0x1a, 0x30, 0xe8, 0x81, 0x73, 0xca, 0x44, 0x9e, 0x16, 0xa9, 0x18, 0x5b, 0x1c, - 0x96, 0x28, 0xe3, 0xed, 0x38, 0xa0, 0xec, 0xe7, 0x6d, 0x64, 0xfa, 0x5e, 0xda, 0x48, 0xc4, 0xa6, - 0xc7, 0x35, 0x74, 0x64, 0xa4, 0x4a, 0x80, 0xac, 0xc1, 0x1c, 0x8b, 0xe3, 0x30, 0x56, 0xc5, 0x43, - 0x6c, 0x79, 0xd5, 0xdb, 0x71, 0xd4, 0xb0, 0x8f, 0xc5, 0x55, 0x4f, 0x25, 0x83, 0x55, 0x81, 0x72, - 0x6a, 0x35, 0x89, 0xc2, 0x20, 0x61, 0xd6, 0x32, 0x86, 0x2e, 0x6a, 0xf3, 0x44, 0xed, 0xc3, 0xfa, - 0xab, 0x01, 0xe5, 0x94, 0x22, 0x79, 0xc8, 0x17, 0x50, 0xec, 0xb5, 0x86, 0xb4, 0x07, 0xdc, 0xcf, - 0x0c, 0xaa, 0x2e, 0xaf, 0xf5, 0x15, 0xd5, 0x12, 0x74, 0x75, 0xe6, 0x13, 0xa8, 0x0c, 0x32, 0x8c, - 0xc8, 0xfe, 0x07, 0xfd, 0x0d, 0x62, 0xb0, 0x5f, 0x69, 0xa7, 0xe1, 0x5f, 0x06, 0x5c, 0xa6, 0x4c, - 0x60, 0x97, 0x83, 0x53, 0xa7, 0xc5, 0xb6, 0xc3, 0xa0, 0xe9, 0xb5, 0xd2, 0x30, 0x57, 0x44, 0x33, - 0x4c, 0x35, 0x63, 0x5f, 0x5c, 0x83, 0x85, 0xba, 0xef, 0xf0, 0x66, 0x18, 0x9f, 0x2a, 0xe5, 0x25, - 0x54, 0x9e, 0xd2, 0x68, 0x77, 0x95, 0xac, 0x40, 0x51, 0x29, 0x3e, 0x0a, 0xdd, 0x34, 0x9d, 0x3a, - 0x89, 0x54, 0x61, 0xfe, 0x30, 0x6c, 0x3d, 0xc1, 0x64, 0xcb, 0x0a, 0x4b, 0xa7, 0xc4, 0x82, 0x92, - 0x62, 0x8c, 0xbb, 0xd5, 0x35, 0x47, 0xfb, 0x68, 0xe4, 0x3d, 0x58, 0x3c, 0x66, 0x49, 0xe2, 0x85, - 0xc1, 0xc1, 0x4e, 0xb5, 0x20, 0xe4, 0x7b, 0x04, 0xd4, 0x7d, 0xcc, 0xc3, 0x98, 0x1d, 0xec, 0x54, - 0xe7, 0xa5, 0x6e, 0x35, 0xb5, 0x7e, 0x61, 0x80, 0x39, 0xca, 0x63, 0x95, 0xbe, 0xcf, 0xa0, 0x20, - 0x0f, 0xa4, 0xf4, 0xfa, 0x7f, 0x3b, 0xca, 0xf2, 0x97, 0xbc, 0x0b, 0x05, 0xa9, 0x5d, 0x55, 0xa1, - 0x9a, 0x59, 0xbf, 0x2a, 0x40, 0xe9, 0x18, 0x37, 0x90, 0xc6, 0xd9, 0x06, 0xe8, 0xa5, 0x47, 0x1d, - 0xe9, 0xc1, 0xa4, 0x69, 0x1c, 0xc4, 0x84, 0x85, 0x3d, 0x75, 0x7c, 0xd4, 0x0d, 0xd6, 0x9d, 0x93, - 0xcf, 0xa1, 0x98, 0x8e, 0x9f, 0x46, 0xbc, 0x9a, 0x13, 0xe7, 0xef, 0x5e, 0xc6, 0xf9, 0xd3, 0x77, - 0x62, 0x6b, 0xa2, 0xea, 0xf4, 0x69, 0x14, 0x72, 0x13, 0x2e, 0x38, 0xbe, 0x1f, 0x9e, 0xa9, 0x92, - 0x12, 0xc5, 0x21, 0x92, 0xb3, 0x40, 0x87, 0x17, 0xb0, 0x55, 0x6a, 0xc4, 0x47, 0x71, 0xec, 0x74, - 0xf0, 0x34, 0x15, 0x04, 0xff, 0xa8, 0x25, 0xec, 0x5a, 0x7b, 0x5e, 0xe0, 0xf8, 0x55, 0x10, 0x3c, - 0x72, 0x82, 0xa7, 0x61, 0xf7, 0x75, 0x14, 0xc6, 0x9c, 0xc5, 0x8f, 0x38, 0x8f, 0xab, 0x45, 0x11, - 0xcc, 0x3e, 0x1a, 0xa9, 0x43, 0x69, 0xdb, 0x69, 0xbc, 0x60, 0x07, 0xa7, 0x48, 0x4c, 0x91, 0x55, - 0x56, 0x2f, 0x13, 0xec, 0x4f, 0x23, 0x1d, 0x52, 0xe9, 0x1a, 0x48, 0x03, 0xca, 0xa9, 0xeb, 0xb2, - 0x42, 0xab, 0x4b, 0x42, 0xe7, 0x83, 0x69, 0x43, 0x29, 0xa5, 0xa5, 0x89, 0x01, 0x95, 0x98, 0xc8, - 0x5d, 0x2c, 0x46, 0x87, 0xb3, 0x6a, 0x59, 0xf8, 0xdc, 0x9d, 0x93, 0x23, 0x28, 0x1f, 0x0b, 0x40, - 0x5e, 0x47, 0x18, 0xee, 0xb1, 0xa4, 0xba, 0x2c, 0x36, 0x70, 0x7d, 0x78, 0x03, 0x3a, 0x70, 0xb7, - 0x05, 0x7b, 0x87, 0x0e, 0x08, 0x9b, 0x0f, 0xa1, 0x32, 0x98, 0xdc, 0x69, 0x80, 0x91, 0xf9, 0x43, - 0xb8, 0x38, 0xc2, 0xa3, 0xb7, 0x6a, 0x3e, 0x7f, 0x32, 0xe0, 0xc2, 0x50, 0x1a, 0xf0, 0x02, 0x10, - 0x45, 0x2f, 0x55, 0x8a, 0x31, 0x39, 0x82, 0x39, 0x4c, 0x73, 0xa2, 0xa0, 0xc0, 0xe6, 0x34, 0x79, - 0xb5, 0x85, 0xa4, 0x8c, 0xbf, 0xd4, 0x62, 0xde, 0x03, 0xe8, 0x11, 0xa7, 0x82, 0x87, 0x5f, 0xc0, - 0x92, 0x4a, 0xb2, 0xea, 0x17, 0x15, 0x89, 0x2a, 0x94, 0x30, 0xa2, 0x86, 0xde, 0xdd, 0x94, 0x9b, - 0xf2, 0x6e, 0xb2, 0xbe, 0x82, 0x65, 0xca, 0x1c, 0x77, 0xcf, 0xf3, 0xd9, 0xf9, 0x2d, 0x18, 0x8b, - 0xdf, 0xf3, 0x59, 0x1d, 0x91, 0x49, 0x5a, 0xfc, 0x6a, 0x4e, 0xee, 0xc3, 0x1c, 0x75, 0x82, 0x16, - 0x53, 0xa6, 0x3f, 0xc8, 0x30, 0x2d, 0x8c, 0x20, 0x2f, 0x95, 0x22, 0xd6, 0x03, 0x58, 0xec, 0xd2, - 0xb0, 0x75, 0x3d, 0x6d, 0x36, 0x13, 0x26, 0xdb, 0x60, 0x8e, 0xaa, 0x19, 0xd2, 0x0f, 0x59, 0xd0, - 0x52, 0xa6, 0x73, 0x54, 0xcd, 0xac, 0x55, 0x84, 0xf3, 0xe9, 0xce, 0x55, 0x68, 0x08, 0xe4, 0x77, - 0x10, 0xbe, 0x19, 0xa2, 0x5e, 0xc5, 0xd8, 0x72, 0xf1, 0x4e, 0x75, 0xdc, 0x1d, 0x2f, 0x3e, 0xdf, - 0xc1, 0x2a, 0xcc, 0xef, 0x78, 0xb1, 0xe6, 0x5f, 0x3a, 0x25, 0xab, 0x78, 0xdb, 0x36, 0xfc, 0xb6, - 0x8b, 0xde, 0x72, 0x16, 0x07, 0xea, 0x5a, 0x19, 0xa0, 0x5a, 0x9f, 0xc8, 0x38, 0x0a, 0x2b, 0x6a, - 0x33, 0x37, 0x61, 0x9e, 0x05, 0x3c, 0xc6, 0x32, 0x92, 0x57, 0x32, 0xb1, 0xe5, 0x03, 0xd9, 0x16, - 0x0f, 0x64, 0x71, 0xf5, 0xd3, 0x94, 0xc5, 0xda, 0x84, 0x65, 0x24, 0x64, 0x27, 0x82, 0x40, 0x5e, - 0xdb, 0xa4, 0x18, 0x5b, 0xf7, 0xa1, 0xd2, 0x13, 0x54, 0xa6, 0x57, 0x21, 0x8f, 0xd8, 0x54, 0xf5, - 0xf5, 0x51, 0x76, 0xc5, 0xba, 0x75, 0x0d, 0x96, 0xd3, 0xe2, 0x3f, 0xd7, 0xa8, 0x45, 0xa0, 0xd2, - 0x63, 0x52, 0xb0, 0x64, 0x09, 0x8a, 0x75, 0x2f, 0x48, 0x6f, 0x6d, 0xeb, 0x8d, 0x01, 0xa5, 0x7a, - 0x18, 0xf4, 0xee, 0xb4, 0x3a, 0x2c, 0xa7, 0xa5, 0xfb, 0xa8, 0x7e, 0xb0, 0xed, 0x44, 0x69, 0x0c, - 0x56, 0x86, 0xcf, 0x87, 0xfa, 0xc4, 0x60, 0x4b, 0xc6, 0xad, 0x3c, 0x5e, 0x7f, 0x74, 0x50, 0x9c, - 0x7c, 0x0a, 0xf3, 0x87, 0x87, 0x5b, 0x42, 0xd3, 0xec, 0x54, 0x9a, 0x52, 0x31, 0xf2, 0x10, 0xe6, - 0x9f, 0x8b, 0x2f, 0x1f, 0x89, 0xba, 0xa2, 0x46, 0x9c, 0x55, 0x19, 0x21, 0xc9, 0x46, 0x59, 0x23, - 0x8c, 0x5d, 0x9a, 0x0a, 0x59, 0xff, 0x36, 0xa0, 0xf8, 0xdc, 0xe9, 0x21, 0xc2, 0x1e, 0x04, 0x7d, - 0x8b, 0x7b, 0x5b, 0x41, 0xd0, 0x4b, 0x30, 0xe7, 0xb3, 0x57, 0xcc, 0x57, 0x67, 0x5c, 0x4e, 0x90, - 0x9a, 0xbc, 0x08, 0x63, 0x59, 0xd6, 0x25, 0x2a, 0x27, 0x58, 0x10, 0x2e, 0xe3, 0x8e, 0xe7, 0x57, - 0xf3, 0x2b, 0x39, 0xbc, 0xe3, 0xe5, 0x0c, 0x33, 0xd7, 0x8e, 0x7d, 0xf5, 0x2e, 0xc0, 0x21, 0xb1, - 0x20, 0xef, 0x05, 0xcd, 0x50, 0xdc, 0x7f, 0xaa, 0x2d, 0xca, 0x16, 0x7d, 0x10, 0x34, 0x43, 0x2a, - 0xd6, 0xc8, 0x55, 0x28, 0xc4, 0x58, 0x7f, 0x49, 0x75, 0x5e, 0x04, 0x65, 0x11, 0xb9, 0x64, 0x95, - 0xaa, 0x05, 0xab, 0x0c, 0x25, 0xe9, 0xb7, 0x4a, 0xfe, 0x6f, 0x66, 0xe1, 0xe2, 0x13, 0x76, 0xb6, - 0x9d, 0xfa, 0x95, 0x06, 0x64, 0x05, 0x8a, 0x5d, 0xda, 0xc1, 0x8e, 0x3a, 0x42, 0x3a, 0x09, 0x8d, - 0x1d, 0x85, 0xed, 0x80, 0xa7, 0x39, 0x14, 0xc6, 0x04, 0x85, 0xaa, 0x05, 0x72, 0x1d, 0xe6, 0x9f, - 0x30, 0x7e, 0x16, 0xc6, 0x2f, 0x85, 0xd7, 0xe5, 0x8d, 0x22, 0xf2, 0x3c, 0x61, 0x1c, 0x01, 0x1c, - 0x4d, 0xd7, 0x10, 0x15, 0x46, 0x29, 0x2a, 0xcc, 0x8f, 0x42, 0x85, 0xe9, 0x2a, 0xd9, 0x84, 0x62, - 0x23, 0x0c, 0x12, 0x1e, 0x3b, 0x1e, 0x1a, 0x9e, 0x13, 0xcc, 0xef, 0x20, 0xb3, 0x4c, 0xec, 0x76, - 0x6f, 0x91, 0xea, 0x9c, 0x64, 0x1d, 0x80, 0xbd, 0xe6, 0xb1, 0xb3, 0x1f, 0x26, 0xdd, 0x17, 0x14, - 0xa0, 0x1c, 0x12, 0x0e, 0xea, 0x54, 0x5b, 0xb5, 0xde, 0x85, 0x4b, 0xfd, 0x11, 0x51, 0xa1, 0x7a, - 0x00, 0xff, 0x47, 0x99, 0xcf, 0x9c, 0x84, 0x4d, 0x1f, 0x2d, 0xcb, 0x84, 0xea, 0xb0, 0xb0, 0x52, - 0xfc, 0x9f, 0x1c, 0x14, 0x77, 0x5f, 0xb3, 0xc6, 0x11, 0x4b, 0x12, 0xa7, 0x25, 0xb0, 0x69, 0x3d, - 0x0e, 0x1b, 0x2c, 0x49, 0xba, 0xba, 0x7a, 0x04, 0xf2, 0x7d, 0xc8, 0x1f, 0x04, 0x1e, 0x57, 0xf7, - 0xe3, 0x6a, 0xe6, 0xd3, 0xc0, 0xe3, 0x4a, 0xe7, 0xfe, 0x0c, 0x15, 0x52, 0xe4, 0x3e, 0xe4, 0xb1, - 0xbb, 0x4c, 0xd2, 0xe1, 0x5d, 0x4d, 0x16, 0x65, 0xc8, 0x96, 0xf8, 0x84, 0xe7, 0x7d, 0xc9, 0x54, - 0x96, 0xd6, 0xb2, 0xaf, 0x26, 0xef, 0x4b, 0xd6, 0xd3, 0xa0, 0x24, 0xc9, 0x2e, 0x22, 0x6b, 0x27, - 0xe6, 0xcc, 0x55, 0xd9, 0xbb, 0x91, 0x05, 0x88, 0x24, 0x67, 0x4f, 0x4b, 0x2a, 0x8b, 0x41, 0xd8, - 0x7d, 0xed, 0x71, 0x55, 0x0d, 0x59, 0x41, 0x40, 0x36, 0xcd, 0x11, 0x9c, 0xa2, 0xf4, 0x4e, 0x18, - 0x30, 0x81, 0xed, 0xb3, 0xa5, 0x91, 0x4d, 0x93, 0xc6, 0x29, 0x86, 0xe1, 0xd8, 0x6b, 0x21, 0xce, - 0x5c, 0x18, 0x1b, 0x06, 0xc9, 0xa8, 0x85, 0x41, 0x12, 0xb6, 0xe6, 0x61, 0x4e, 0xc0, 0x20, 0xeb, - 0x77, 0x06, 0x14, 0xb5, 0x3c, 0x4d, 0x50, 0x77, 0xef, 0x41, 0x1e, 0x9f, 0xef, 0x2a, 0xff, 0x0b, - 0xa2, 0xea, 0x18, 0x77, 0xa8, 0xa0, 0x62, 0xe3, 0xd8, 0x73, 0x65, 0x53, 0x5c, 0xa2, 0x38, 0x44, - 0xca, 0x33, 0xde, 0x11, 0x29, 0x5b, 0xa0, 0x38, 0x24, 0x37, 0x61, 0xe1, 0x98, 0x35, 0xda, 0xb1, - 0xc7, 0x3b, 0x22, 0x09, 0xe5, 0x8d, 0x8a, 0x68, 0x27, 0x8a, 0x26, 0x8a, 0xb3, 0xcb, 0x61, 0x3d, - 0xc6, 0xc3, 0xd9, 0xdb, 0x20, 0x81, 0xfc, 0x36, 0xbe, 0xc8, 0x70, 0x67, 0x4b, 0x54, 0x8c, 0xf1, - 0x51, 0xbc, 0x3b, 0xee, 0x51, 0xbc, 0x9b, 0x3e, 0x8a, 0xfb, 0x93, 0x8a, 0xb7, 0x8f, 0x16, 0x64, - 0xeb, 0x11, 0x2c, 0x76, 0x0f, 0x1e, 0x29, 0xc3, 0xec, 0x9e, 0xab, 0x2c, 0xcd, 0xee, 0xb9, 0xe8, - 0xca, 0xee, 0xd3, 0x3d, 0x61, 0x65, 0x81, 0xe2, 0xb0, 0x0b, 0x12, 0x72, 0x1a, 0x48, 0xd8, 0xc4, - 0xe7, 0xbe, 0x76, 0xfa, 0x90, 0x89, 0x86, 0x67, 0x49, 0xba, 0x65, 0x1c, 0x4b, 0x37, 0xfc, 0x44, - 0xe8, 0x12, 0x6e, 0xf8, 0x89, 0x75, 0x0d, 0x96, 0xfa, 0xf2, 0x85, 0x4c, 0xe2, 0x7d, 0xa9, 0xb0, - 0x24, 0x8e, 0xd7, 0x19, 0x2c, 0x0f, 0x7c, 0x72, 0x22, 0xd7, 0xa1, 0x20, 0x3f, 0x6d, 0x54, 0x66, - 0xcc, 0xcb, 0x5f, 0x7f, 0xb3, 0xf2, 0xce, 0x00, 0x83, 0x5c, 0x44, 0xb6, 0xad, 0x76, 0xe0, 0xfa, - 0xac, 0x62, 0x8c, 0x64, 0x93, 0x8b, 0x66, 0xfe, 0xd7, 0x7f, 0xb8, 0x32, 0xb3, 0xee, 0xc0, 0x85, - 0xa1, 0xcf, 0x25, 0xe4, 0x1a, 0xe4, 0x8f, 0x99, 0xdf, 0x4c, 0xcd, 0x0c, 0x31, 0xe0, 0x22, 0xb9, - 0x0a, 0x39, 0xea, 0x9c, 0x55, 0x0c, 0xb3, 0xfa, 0xf5, 0x37, 0x2b, 0x97, 0x86, 0xbf, 0xb9, 0x38, - 0x67, 0xd2, 0xc4, 0xc6, 0x5f, 0x00, 0x16, 0x0f, 0x0f, 0xb7, 0xb6, 0x62, 0xcf, 0x6d, 0x31, 0xf2, - 0x4b, 0x03, 0xc8, 0xf0, 0xc3, 0x96, 0xdc, 0xc9, 0xae, 0xf1, 0xd1, 0x2f, 0x7f, 0xf3, 0xee, 0x94, - 0x52, 0x0a, 0x69, 0x7c, 0x0e, 0x73, 0x02, 0x1e, 0x93, 0x0f, 0x27, 0x7c, 0x25, 0x99, 0x6b, 0xe3, - 0x19, 0x95, 0xee, 0x06, 0x2c, 0xa4, 0x10, 0x93, 0xac, 0x67, 0x6e, 0xaf, 0x0f, 0x41, 0x9b, 0x1f, - 0x4d, 0xc4, 0xab, 0x8c, 0xfc, 0x14, 0xe6, 0x15, 0x72, 0x24, 0x37, 0xc6, 0xc8, 0xf5, 0x30, 0xac, - 0xb9, 0x3e, 0x09, 0x6b, 0xcf, 0x8d, 0x14, 0x21, 0x66, 0xba, 0x31, 0x80, 0x3f, 0x33, 0xdd, 0x18, - 0x82, 0x9c, 0x8d, 0xde, 0xbb, 0x32, 0xd3, 0xc8, 0x00, 0xde, 0xcc, 0x34, 0x32, 0x08, 0x3b, 0xc9, - 0x73, 0xc8, 0x23, 0xec, 0x24, 0x59, 0xed, 0x57, 0xc3, 0xa5, 0x66, 0xd6, 0x99, 0xe8, 0xc3, 0xab, - 0x3f, 0xc1, 0x6b, 0x4a, 0x7c, 0x42, 0xc8, 0xbe, 0xa0, 0xb4, 0x2f, 0x82, 0xe6, 0x8d, 0x09, 0x38, - 0x7b, 0xea, 0xd5, 0xf3, 0x7b, 0x6d, 0x82, 0xcf, 0x72, 0xe3, 0xd5, 0x0f, 0x7c, 0x00, 0x0c, 0xa1, - 0xa4, 0xa3, 0x0f, 0x62, 0x67, 0x88, 0x8e, 0x00, 0x6e, 0x66, 0x6d, 0x62, 0x7e, 0x65, 0xf0, 0x2b, - 0x7c, 0x7b, 0xf5, 0x23, 0x13, 0xb2, 0x91, 0x19, 0x8e, 0x91, 0x18, 0xc8, 0xbc, 0x3d, 0x95, 0x8c, - 0x32, 0xee, 0x48, 0xe4, 0xa3, 0xd0, 0x0d, 0xc9, 0xbe, 0xc8, 0xbb, 0x08, 0xc9, 0x9c, 0x90, 0x6f, - 0xcd, 0xb8, 0x65, 0xe0, 0x39, 0x43, 0xc4, 0x9b, 0xa9, 0x5b, 0x7b, 0x0a, 0x64, 0x9e, 0x33, 0x1d, - 0x3a, 0x6f, 0x95, 0xbe, 0x7d, 0x73, 0xc5, 0xf8, 0xfb, 0x9b, 0x2b, 0xc6, 0x3f, 0xdf, 0x5c, 0x31, - 0x4e, 0x0a, 0xe2, 0x7f, 0xce, 0xdb, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xc4, 0x91, 0xe5, 0xca, - 0x70, 0x1e, 0x00, 0x00, + 0xd0, 0xb2, 0x92, 0x53, 0x0f, 0x05, 0x8a, 0x9c, 0x8a, 0x1e, 0x7a, 0x0b, 0x0a, 0xb4, 0x40, 0xcf, + 0xed, 0x1f, 0xd0, 0x9c, 0x03, 0xf4, 0xd2, 0x73, 0x0f, 0x41, 0xe1, 0x3f, 0xa2, 0x40, 0x6f, 0xc5, + 0x9b, 0x99, 0x25, 0x87, 0x3f, 0xb4, 0x22, 0xeb, 0x13, 0x67, 0xde, 0xbc, 0x1f, 0xf3, 0xde, 0x9b, + 0xf7, 0xe6, 0x33, 0x4b, 0xa8, 0x74, 0x1c, 0xce, 0x4e, 0x9c, 0x53, 0x3b, 0x8a, 0x43, 0x1e, 0x92, + 0xcb, 0xc7, 0xe1, 0xd1, 0xa9, 0x7d, 0xd4, 0xf5, 0x7c, 0xf7, 0xa5, 0xc7, 0xed, 0x57, 0xff, 0x6f, + 0xb7, 0xe3, 0x30, 0xe0, 0x2c, 0x70, 0xcd, 0x8f, 0x3b, 0x1e, 0x7f, 0xd1, 0x3d, 0xb2, 0x5b, 0xe1, + 0x71, 0xa3, 0x13, 0x76, 0xc2, 0x86, 0x90, 0x38, 0xea, 0xb6, 0xc5, 0x4c, 0x4c, 0xc4, 0x48, 0x6a, + 0x32, 0xd7, 0x86, 0xd9, 0x3b, 0x61, 0xd8, 0xf1, 0x99, 0x13, 0x79, 0x89, 0x1a, 0x36, 0xe2, 0xa8, + 0xd5, 0x48, 0xb8, 0xc3, 0xbb, 0x89, 0x92, 0xb9, 0xa9, 0xc9, 0xe0, 0x46, 0x1a, 0xe9, 0x46, 0x1a, + 0x49, 0xe8, 0xbf, 0x62, 0x71, 0x23, 0x3a, 0x6a, 0x84, 0x51, 0xca, 0xdd, 0x38, 0x93, 0xdb, 0x89, + 0xbc, 0x06, 0x3f, 0x8d, 0x58, 0xd2, 0x38, 0x09, 0xe3, 0x97, 0x2c, 0x56, 0x02, 0xb7, 0xcf, 0x14, + 0xe8, 0x72, 0xcf, 0x47, 0xa9, 0x96, 0x13, 0x25, 0x68, 0x04, 0x7f, 0x95, 0x90, 0xee, 0x36, 0x0f, + 0x03, 0x2f, 0xe1, 0x9e, 0xd7, 0xf1, 0x1a, 0xed, 0x44, 0xc8, 0x48, 0x2b, 0xe8, 0x84, 0x62, 0xbf, + 0x9b, 0xe1, 0x42, 0x37, 0x6e, 0xb1, 0x28, 0xf4, 0xbd, 0xd6, 0x29, 0xda, 0x90, 0x23, 0x29, 0x66, + 0xfd, 0x3d, 0x0f, 0x05, 0xca, 0x92, 0xae, 0xcf, 0xc9, 0x32, 0x54, 0x62, 0xd6, 0xde, 0x62, 0x51, + 0xcc, 0x5a, 0x0e, 0x67, 0x6e, 0xdd, 0x58, 0x32, 0x56, 0x16, 0x76, 0x67, 0xe8, 0x20, 0x99, 0xfc, + 0x04, 0xaa, 0x31, 0x6b, 0x27, 0x1a, 0xe3, 0xec, 0x92, 0xb1, 0x52, 0x5a, 0xfb, 0xc8, 0x3e, 0x33, + 0x87, 0x36, 0x65, 0xed, 0x03, 0x27, 0xea, 0x8b, 0xec, 0xce, 0xd0, 0x21, 0x25, 0x64, 0x0d, 0x72, + 0x31, 0x6b, 0xd7, 0x73, 0x42, 0xd7, 0x95, 0x6c, 0x5d, 0xbb, 0x33, 0x14, 0x99, 0xc9, 0x3a, 0xe4, + 0x51, 0x4b, 0x3d, 0x2f, 0x84, 0xae, 0x9e, 0xbb, 0x81, 0xdd, 0x19, 0x2a, 0x04, 0xc8, 0x63, 0x28, + 0x1e, 0x33, 0xee, 0xb8, 0x0e, 0x77, 0xea, 0xb0, 0x94, 0x5b, 0x29, 0xad, 0x35, 0x32, 0x85, 0x31, + 0x40, 0xf6, 0x81, 0x92, 0xd8, 0x0e, 0x78, 0x7c, 0x4a, 0x7b, 0x0a, 0xc8, 0x73, 0x28, 0x3b, 0x9c, + 0x33, 0x4c, 0x86, 0x17, 0x06, 0x49, 0xbd, 0x2c, 0x14, 0xde, 0x3e, 0x5f, 0xe1, 0x23, 0x4d, 0x4a, + 0x2a, 0x1d, 0x50, 0x64, 0x3e, 0x80, 0xca, 0x80, 0x4d, 0x52, 0x83, 0xdc, 0x4b, 0x76, 0x2a, 0x13, + 0x43, 0x71, 0x48, 0x2e, 0xc1, 0xdc, 0x2b, 0xc7, 0xef, 0x32, 0x91, 0x83, 0x32, 0x95, 0x93, 0xfb, + 0xb3, 0xf7, 0x0c, 0xf3, 0x05, 0x5c, 0x18, 0xd1, 0x3f, 0x46, 0xc1, 0x8f, 0x74, 0x05, 0xa5, 0xb5, + 0x0f, 0x33, 0x76, 0xad, 0xab, 0xd3, 0x2c, 0x6d, 0x14, 0xa1, 0x10, 0x0b, 0x87, 0xac, 0xdf, 0x1b, + 0x50, 0x1b, 0x4e, 0x35, 0xd9, 0x53, 0x49, 0x32, 0x44, 0x58, 0xee, 0x4e, 0x71, 0x4a, 0x90, 0xa0, + 0x02, 0x23, 0x54, 0x98, 0xeb, 0xb0, 0xd0, 0x23, 0x9d, 0x17, 0x8c, 0x05, 0x6d, 0x8b, 0xd6, 0x3a, + 0xe4, 0x28, 0x6b, 0x93, 0x2a, 0xcc, 0x7a, 0xea, 0x5c, 0xd3, 0x59, 0xcf, 0x25, 0x4b, 0x90, 0x73, + 0x59, 0x5b, 0xb9, 0x5e, 0xb5, 0xa3, 0x23, 0x7b, 0x8b, 0xb5, 0xbd, 0xc0, 0x43, 0x17, 0x29, 0x2e, + 0x59, 0x7f, 0x34, 0xb0, 0x3e, 0x70, 0x5b, 0xe4, 0x93, 0x01, 0x3f, 0xce, 0x3f, 0xed, 0x23, 0xbb, + 0x7f, 0x9e, 0xbd, 0xfb, 0x3b, 0x83, 0x99, 0x38, 0xa7, 0x04, 0x74, 0xef, 0x7e, 0x0a, 0x65, 0x3d, + 0x37, 0x64, 0x17, 0x4a, 0xda, 0x39, 0x52, 0x1b, 0x5e, 0x9e, 0x2c, 0xb3, 0x54, 0x17, 0xb5, 0xfe, + 0x9c, 0x83, 0x92, 0xb6, 0x48, 0x1e, 0x42, 0xfe, 0xa5, 0x17, 0xc8, 0x10, 0x56, 0xd7, 0x56, 0x27, + 0x53, 0xf9, 0xd8, 0x0b, 0x5c, 0x2a, 0xe4, 0x48, 0x53, 0xab, 0xbb, 0x59, 0xb1, 0xad, 0x3b, 0x93, + 0xe9, 0x38, 0xb3, 0xf8, 0x6e, 0x4d, 0xd1, 0x36, 0x64, 0xd3, 0x20, 0x90, 0x8f, 0x1c, 0xfe, 0x42, + 0x34, 0x8d, 0x05, 0x2a, 0xc6, 0xe4, 0x16, 0x5c, 0xf4, 0x82, 0x67, 0x21, 0x0f, 0x9b, 0x31, 0x73, + 0x3d, 0x3c, 0x7c, 0xcf, 0x4e, 0x23, 0x56, 0x9f, 0x13, 0x2c, 0xe3, 0x96, 0x48, 0x13, 0xaa, 0x92, + 0x7c, 0xd8, 0x3d, 0xfa, 0x05, 0x6b, 0xf1, 0xa4, 0x5e, 0x10, 0xfe, 0xac, 0x64, 0x6c, 0x61, 0x4f, + 0x17, 0xa0, 0x43, 0xf2, 0x6f, 0x55, 0xed, 0xd6, 0x5f, 0x0d, 0xa8, 0x0c, 0xa8, 0x27, 0x9f, 0x0e, + 0xa4, 0xea, 0xe6, 0xa4, 0xdb, 0xd2, 0x92, 0xf5, 0x19, 0x14, 0x5c, 0xaf, 0xc3, 0x12, 0x2e, 0x52, + 0xb5, 0xb0, 0xb1, 0xf6, 0xdd, 0xf7, 0xef, 0xcf, 0xfc, 0xf3, 0xfb, 0xf7, 0x57, 0xb5, 0xab, 0x26, + 0x8c, 0x58, 0xd0, 0x0a, 0x03, 0xee, 0x78, 0x01, 0x8b, 0xf1, 0x82, 0xfd, 0x58, 0x8a, 0xd8, 0x5b, + 0xe2, 0x87, 0x2a, 0x0d, 0x18, 0xf4, 0xc0, 0x39, 0x66, 0x22, 0x4f, 0x0b, 0x54, 0x8c, 0x2d, 0x0e, + 0x15, 0xca, 0x78, 0x37, 0x0e, 0x28, 0xfb, 0x65, 0x17, 0x99, 0x7e, 0x90, 0x36, 0x12, 0xb1, 0xe9, + 0xf3, 0x1a, 0x3a, 0x32, 0x52, 0x25, 0x40, 0x56, 0x60, 0x8e, 0xc5, 0x71, 0x18, 0xab, 0xe2, 0x21, + 0xb6, 0xbc, 0xea, 0xed, 0x38, 0x6a, 0xd9, 0x87, 0xe2, 0xaa, 0xa7, 0x92, 0xc1, 0xaa, 0x41, 0x35, + 0xb5, 0x9a, 0x44, 0x61, 0x90, 0x30, 0x6b, 0x11, 0x43, 0x17, 0x75, 0x79, 0xa2, 0xf6, 0x61, 0x7d, + 0x6b, 0x40, 0x35, 0xa5, 0x48, 0x1e, 0xf2, 0x05, 0x94, 0xfa, 0xad, 0x21, 0xed, 0x01, 0xf7, 0x33, + 0x83, 0xaa, 0xcb, 0x6b, 0x7d, 0x45, 0xb5, 0x04, 0x5d, 0x9d, 0xf9, 0x04, 0x6a, 0xc3, 0x0c, 0x63, + 0xb2, 0xff, 0xc1, 0x60, 0x83, 0x18, 0xee, 0x57, 0xda, 0x69, 0xf8, 0x76, 0x16, 0x2e, 0x53, 0x26, + 0xb0, 0xcb, 0xde, 0xb1, 0xd3, 0x61, 0x9b, 0x61, 0xd0, 0xf6, 0x3a, 0x69, 0x98, 0x6b, 0xa2, 0x19, + 0xa6, 0x9a, 0xb1, 0x2f, 0xae, 0x40, 0xb1, 0xe9, 0x3b, 0xbc, 0x1d, 0xc6, 0xc7, 0x4a, 0x79, 0x19, + 0x95, 0xa7, 0x34, 0xda, 0x5b, 0x25, 0x4b, 0x50, 0x52, 0x8a, 0x0f, 0x42, 0x37, 0x4d, 0xa7, 0x4e, + 0x22, 0x75, 0x98, 0xdf, 0x0f, 0x3b, 0x4f, 0x30, 0xd9, 0xb2, 0xc2, 0xd2, 0x29, 0xb1, 0xa0, 0xac, + 0x18, 0xe3, 0x5e, 0x75, 0xcd, 0xd1, 0x01, 0x1a, 0x79, 0x0f, 0x16, 0x0e, 0x59, 0x92, 0x78, 0x61, + 0xb0, 0xb7, 0x55, 0x2f, 0x08, 0xf9, 0x3e, 0x01, 0x75, 0x1f, 0xf2, 0x30, 0x66, 0x7b, 0x5b, 0xf5, + 0x79, 0xa9, 0x5b, 0x4d, 0xc9, 0x01, 0x54, 0x0f, 0x05, 0xce, 0x69, 0x22, 0xba, 0xf1, 0x58, 0x52, + 0x2f, 0x8a, 0x14, 0x5d, 0x1f, 0x4d, 0x91, 0x8e, 0x87, 0x6c, 0xc1, 0x7e, 0x4a, 0x87, 0x84, 0xad, + 0xdf, 0x19, 0x60, 0x8e, 0x0b, 0xa0, 0x3a, 0x0d, 0x9f, 0x41, 0x41, 0x9e, 0x6f, 0x19, 0xc4, 0xff, + 0xad, 0x32, 0xe4, 0x2f, 0x79, 0x17, 0x0a, 0x52, 0xbb, 0x2a, 0x6a, 0x35, 0x4b, 0xb3, 0x94, 0xeb, + 0x65, 0xc9, 0xfa, 0x75, 0x01, 0xca, 0x87, 0xb8, 0xa5, 0x34, 0x91, 0x36, 0x40, 0x3f, 0xff, 0xaa, + 0x66, 0x86, 0x4f, 0x85, 0xc6, 0x41, 0x4c, 0x28, 0xee, 0xa8, 0xf3, 0xa9, 0xae, 0xc8, 0xde, 0x9c, + 0x7c, 0x0e, 0xa5, 0x74, 0xfc, 0x34, 0xe2, 0xf5, 0x9c, 0x88, 0xde, 0xbd, 0x8c, 0x03, 0xae, 0xef, + 0xc4, 0xd6, 0x44, 0xd5, 0xf1, 0xd6, 0x28, 0xe4, 0x26, 0x5c, 0x70, 0x7c, 0x3f, 0x3c, 0x51, 0x35, + 0x2b, 0xaa, 0x4f, 0x64, 0xbf, 0x48, 0x47, 0x17, 0xb0, 0x17, 0x6b, 0xc4, 0x47, 0x71, 0xec, 0x9c, + 0x62, 0x20, 0x0a, 0x82, 0x7f, 0xdc, 0x12, 0xb6, 0xc5, 0x1d, 0x2f, 0x70, 0xfc, 0x3a, 0x08, 0x1e, + 0x39, 0xc1, 0xe3, 0xb6, 0xfd, 0x3a, 0x0a, 0x63, 0xce, 0xe2, 0x47, 0x9c, 0xc7, 0xf5, 0x92, 0x08, + 0xef, 0x00, 0x8d, 0x34, 0xa1, 0xbc, 0xe9, 0xb4, 0x5e, 0xb0, 0xbd, 0x63, 0x24, 0xa6, 0xd0, 0x2d, + 0xab, 0x59, 0x0a, 0xf6, 0xa7, 0x91, 0x8e, 0xd9, 0x74, 0x0d, 0xa4, 0x05, 0xd5, 0xd4, 0x75, 0xd9, + 0x02, 0xea, 0x15, 0xa1, 0xf3, 0xc1, 0xb4, 0xa1, 0x94, 0xd2, 0xd2, 0xc4, 0x90, 0x4a, 0x4c, 0xe4, + 0x36, 0x56, 0xbb, 0xc3, 0x59, 0xbd, 0x2a, 0x7c, 0xee, 0xcd, 0xc7, 0x54, 0xc2, 0xe2, 0x5b, 0x54, + 0x82, 0xf9, 0x10, 0x6a, 0xc3, 0xc9, 0x9d, 0x06, 0x79, 0x99, 0x3f, 0x86, 0x8b, 0x63, 0x3c, 0x7a, + 0xab, 0xee, 0xf6, 0x17, 0x03, 0x2e, 0x8c, 0xa4, 0x01, 0x6f, 0x18, 0xd1, 0x55, 0xa4, 0x4a, 0x31, + 0x26, 0x07, 0x30, 0x87, 0x69, 0x4e, 0x14, 0xd6, 0x58, 0x9f, 0x26, 0xaf, 0xb6, 0x90, 0x94, 0xf1, + 0x97, 0x5a, 0xcc, 0x7b, 0x00, 0x7d, 0xe2, 0x54, 0xf8, 0xf3, 0x0b, 0xa8, 0xa8, 0x24, 0xab, 0x0e, + 0x52, 0x93, 0xb0, 0x45, 0x09, 0x23, 0x2c, 0xe9, 0x5f, 0x7e, 0xb9, 0x29, 0x2f, 0x3f, 0xeb, 0x2b, + 0x58, 0xa4, 0xcc, 0x71, 0x77, 0x3c, 0x9f, 0x9d, 0xdd, 0xe3, 0xb1, 0xf8, 0x3d, 0x9f, 0x35, 0x11, + 0xfa, 0xa4, 0xc5, 0xaf, 0xe6, 0xe4, 0x3e, 0xcc, 0x51, 0x27, 0xe8, 0x30, 0x65, 0xfa, 0x83, 0x0c, + 0xd3, 0xc2, 0x08, 0xf2, 0x52, 0x29, 0x62, 0x3d, 0x80, 0x85, 0x1e, 0x0d, 0x9b, 0xd9, 0xd3, 0x76, + 0x3b, 0x61, 0xb2, 0x31, 0xe6, 0xa8, 0x9a, 0x21, 0x7d, 0x9f, 0x05, 0x1d, 0x65, 0x3a, 0x47, 0xd5, + 0xcc, 0x5a, 0xc6, 0xf7, 0x42, 0xba, 0x73, 0x15, 0x1a, 0x02, 0xf9, 0x2d, 0xc4, 0x87, 0x86, 0xa8, + 0x57, 0x31, 0xb6, 0x5c, 0xbc, 0xb4, 0x1d, 0x77, 0xcb, 0x8b, 0xcf, 0x76, 0xb0, 0x0e, 0xf3, 0x5b, + 0x5e, 0xac, 0xf9, 0x97, 0x4e, 0xc9, 0x32, 0x5e, 0xe7, 0x2d, 0xbf, 0xeb, 0xa2, 0xb7, 0x9c, 0xc5, + 0x81, 0xea, 0xaa, 0x43, 0x54, 0xeb, 0x13, 0x19, 0x47, 0x61, 0x45, 0x6d, 0xe6, 0x26, 0xcc, 0xb3, + 0x80, 0xc7, 0x58, 0x46, 0xf2, 0xce, 0x27, 0xb6, 0x7c, 0x81, 0xdb, 0xe2, 0x05, 0x2e, 0xb0, 0x05, + 0x4d, 0x59, 0xac, 0x75, 0x58, 0x44, 0x42, 0x76, 0x22, 0x08, 0xe4, 0xb5, 0x4d, 0x8a, 0xb1, 0x75, + 0x1f, 0x6a, 0x7d, 0x41, 0x65, 0x7a, 0x19, 0xf2, 0x08, 0x7e, 0x55, 0x5f, 0x1f, 0x67, 0x57, 0xac, + 0x5b, 0xd7, 0x60, 0x31, 0x2d, 0xfe, 0x33, 0x8d, 0x5a, 0x04, 0x6a, 0x7d, 0x26, 0x85, 0x7b, 0x2a, + 0x50, 0x6a, 0x7a, 0x41, 0x0a, 0x0b, 0xac, 0x37, 0x06, 0x94, 0x9b, 0x61, 0xd0, 0xbf, 0xe5, 0x9a, + 0xb0, 0x98, 0x96, 0xee, 0xa3, 0xe6, 0xde, 0xa6, 0x13, 0xa5, 0x31, 0x58, 0x1a, 0x3d, 0x1f, 0xea, + 0x1b, 0x86, 0x2d, 0x19, 0x37, 0xf2, 0x78, 0x21, 0xd2, 0x61, 0x71, 0xf2, 0x29, 0xcc, 0xef, 0xef, + 0x6f, 0x08, 0x4d, 0xb3, 0x53, 0x69, 0x4a, 0xc5, 0xc8, 0x43, 0x98, 0x7f, 0x2e, 0x3e, 0xad, 0x24, + 0xea, 0x8a, 0x1a, 0x73, 0x56, 0x65, 0x84, 0x24, 0x1b, 0x65, 0xad, 0x30, 0x76, 0x69, 0x2a, 0x64, + 0xfd, 0xdb, 0x80, 0xd2, 0x73, 0xa7, 0x0f, 0x39, 0xfb, 0x18, 0xf7, 0x2d, 0x6e, 0x72, 0x85, 0x71, + 0x2f, 0xc1, 0x9c, 0xcf, 0x5e, 0x31, 0x5f, 0x9d, 0x71, 0x39, 0x41, 0x6a, 0xf2, 0x22, 0x8c, 0x65, + 0x59, 0x97, 0xa9, 0x9c, 0x60, 0x41, 0xb8, 0x8c, 0x3b, 0x9e, 0x5f, 0xcf, 0x2f, 0xe5, 0xf0, 0xd6, + 0x97, 0x33, 0xcc, 0x5c, 0x37, 0xf6, 0xd5, 0xc3, 0x03, 0x87, 0xc4, 0x82, 0xbc, 0x17, 0xb4, 0x43, + 0x71, 0xff, 0xa9, 0xb6, 0x28, 0x5b, 0xf4, 0x5e, 0xd0, 0x0e, 0xa9, 0x58, 0x23, 0x57, 0xa1, 0x10, + 0x63, 0xfd, 0x25, 0xf5, 0x79, 0x11, 0x94, 0x05, 0xe4, 0x92, 0x55, 0xaa, 0x16, 0xac, 0x2a, 0x94, + 0xa5, 0xdf, 0x2a, 0xf9, 0xbf, 0x9d, 0x85, 0x8b, 0x4f, 0xd8, 0xc9, 0x66, 0xea, 0x57, 0x1a, 0x90, + 0x25, 0x28, 0xf5, 0x68, 0x7b, 0x5b, 0xea, 0x08, 0xe9, 0x24, 0x34, 0x76, 0x10, 0x76, 0x03, 0x9e, + 0xe6, 0x50, 0x18, 0x13, 0x14, 0xaa, 0x16, 0xc8, 0x75, 0x98, 0x7f, 0xc2, 0xf8, 0x49, 0x18, 0xbf, + 0x14, 0x5e, 0x57, 0xd7, 0x4a, 0xc8, 0xf3, 0x84, 0x71, 0x44, 0x88, 0x34, 0x5d, 0x43, 0xd8, 0x19, + 0xa5, 0xb0, 0x33, 0x3f, 0x0e, 0x76, 0xa6, 0xab, 0x64, 0x1d, 0x4a, 0xad, 0x30, 0x48, 0x78, 0xec, + 0x78, 0x68, 0x78, 0x4e, 0x30, 0xbf, 0x83, 0xcc, 0x32, 0xb1, 0x9b, 0xfd, 0x45, 0xaa, 0x73, 0x92, + 0x55, 0x00, 0xf6, 0x9a, 0xc7, 0xce, 0x6e, 0x98, 0xf4, 0x9e, 0x68, 0x80, 0x72, 0x48, 0xd8, 0x6b, + 0x52, 0x6d, 0xd5, 0x7a, 0x17, 0x2e, 0x0d, 0x46, 0x44, 0x85, 0xea, 0x01, 0xfc, 0x1f, 0x65, 0x3e, + 0x73, 0x12, 0x36, 0x7d, 0xb4, 0x2c, 0x13, 0xea, 0xa3, 0xc2, 0x4a, 0xf1, 0x7f, 0x72, 0x50, 0xda, + 0x7e, 0xcd, 0x5a, 0x07, 0x2c, 0x49, 0x9c, 0x8e, 0x00, 0xbf, 0xcd, 0x38, 0x6c, 0xb1, 0x24, 0xe9, + 0xe9, 0xea, 0x13, 0xc8, 0x0f, 0x21, 0xbf, 0x17, 0x78, 0x5c, 0xdd, 0x8f, 0xcb, 0x99, 0x6f, 0x0f, + 0x8f, 0x2b, 0x9d, 0xbb, 0x33, 0x54, 0x48, 0x91, 0xfb, 0x90, 0xc7, 0xee, 0x32, 0x49, 0x87, 0x77, + 0x35, 0x59, 0x94, 0x21, 0x1b, 0xe2, 0x1b, 0xa1, 0xf7, 0x25, 0x53, 0x59, 0x5a, 0xc9, 0xbe, 0x9a, + 0xbc, 0x2f, 0x59, 0x5f, 0x83, 0x92, 0x24, 0xdb, 0x08, 0xdd, 0x9d, 0x98, 0x33, 0x57, 0x65, 0xef, + 0x46, 0x16, 0x20, 0x92, 0x9c, 0x7d, 0x2d, 0xa9, 0x2c, 0x06, 0x61, 0xfb, 0xb5, 0xc7, 0x55, 0x35, + 0x64, 0x05, 0x01, 0xd9, 0x34, 0x47, 0x70, 0x8a, 0xd2, 0x5b, 0x61, 0xc0, 0xc4, 0xe3, 0x21, 0x5b, + 0x1a, 0xd9, 0x34, 0x69, 0x9c, 0x62, 0x18, 0x0e, 0xbd, 0x0e, 0xe2, 0xcc, 0xe2, 0xb9, 0x61, 0x90, + 0x8c, 0x5a, 0x18, 0x24, 0x61, 0x63, 0x1e, 0xe6, 0x04, 0x0c, 0xb2, 0xfe, 0x60, 0x40, 0x49, 0xcb, + 0xd3, 0x04, 0x75, 0xf7, 0x1e, 0xe4, 0x0f, 0x98, 0xf8, 0x6e, 0x82, 0xc6, 0x8b, 0xa2, 0xea, 0x18, + 0x77, 0xa8, 0xa0, 0x62, 0xe3, 0xd8, 0x71, 0x65, 0x53, 0xac, 0x50, 0x1c, 0x22, 0xe5, 0x19, 0x3f, + 0x15, 0x29, 0x2b, 0x52, 0x1c, 0x92, 0x9b, 0x50, 0x3c, 0x64, 0xad, 0x6e, 0xec, 0xf1, 0x53, 0x91, + 0x84, 0xea, 0x5a, 0x4d, 0xb4, 0x13, 0x45, 0x13, 0xc5, 0xd9, 0xe3, 0xb0, 0x1e, 0xe3, 0xe1, 0xec, + 0x6f, 0x90, 0x40, 0x7e, 0x13, 0x9f, 0x7c, 0xb8, 0xb3, 0x0a, 0x15, 0x63, 0x7c, 0x75, 0x6f, 0x9f, + 0xf7, 0xea, 0xde, 0x4e, 0x5f, 0xdd, 0x83, 0x49, 0xc5, 0xdb, 0x47, 0x0b, 0xb2, 0xf5, 0x08, 0x16, + 0x7a, 0x07, 0x8f, 0x54, 0x61, 0x76, 0xc7, 0x55, 0x96, 0x66, 0x77, 0x5c, 0x74, 0x65, 0xfb, 0xe9, + 0x8e, 0xb0, 0x52, 0xa4, 0x38, 0xec, 0x81, 0x84, 0x9c, 0x06, 0x12, 0xd6, 0xa1, 0x32, 0x70, 0xfa, + 0x90, 0x89, 0x86, 0x27, 0x49, 0xba, 0x65, 0x1c, 0x4b, 0x37, 0xfc, 0x44, 0xe8, 0x12, 0x6e, 0xf8, + 0x89, 0x75, 0x0d, 0x2a, 0x03, 0xf9, 0x42, 0x26, 0xf1, 0x80, 0x55, 0x58, 0x12, 0xc7, 0xab, 0x0c, + 0x16, 0x87, 0xbe, 0x69, 0x91, 0xeb, 0x50, 0x90, 0xdf, 0x4e, 0x6a, 0x33, 0xe6, 0xe5, 0xaf, 0xbf, + 0x59, 0x7a, 0x67, 0x88, 0x41, 0x2e, 0x22, 0xdb, 0x46, 0x37, 0x70, 0x7d, 0x56, 0x33, 0xc6, 0xb2, + 0xc9, 0x45, 0x33, 0xff, 0x9b, 0x3f, 0x5d, 0x99, 0x59, 0x75, 0xe0, 0xc2, 0xc8, 0xf7, 0x18, 0x72, + 0x0d, 0xf2, 0x87, 0xcc, 0x6f, 0xa7, 0x66, 0x46, 0x18, 0x70, 0x91, 0x5c, 0x85, 0x1c, 0x75, 0x4e, + 0x6a, 0x86, 0x59, 0xff, 0xfa, 0x9b, 0xa5, 0x4b, 0xa3, 0x1f, 0x75, 0x9c, 0x13, 0x69, 0x62, 0xed, + 0x6f, 0x00, 0x0b, 0xfb, 0xfb, 0x1b, 0x1b, 0xb1, 0xe7, 0x76, 0x18, 0xf9, 0x95, 0x01, 0x64, 0xf4, + 0xa9, 0x4b, 0xee, 0x64, 0xd7, 0xf8, 0xf8, 0x4f, 0x0b, 0xe6, 0xdd, 0x29, 0xa5, 0x14, 0xd2, 0xf8, + 0x1c, 0xe6, 0x04, 0x3c, 0x26, 0x1f, 0x4e, 0xf8, 0x4a, 0x32, 0x57, 0xce, 0x67, 0x54, 0xba, 0x5b, + 0x50, 0x4c, 0x21, 0x26, 0x59, 0xcd, 0xdc, 0xde, 0x00, 0x82, 0x36, 0x3f, 0x9a, 0x88, 0x57, 0x19, + 0xf9, 0x39, 0xcc, 0x2b, 0xe4, 0x48, 0x6e, 0x9c, 0x23, 0xd7, 0xc7, 0xb0, 0xe6, 0xea, 0x24, 0xac, + 0x7d, 0x37, 0x52, 0x84, 0x98, 0xe9, 0xc6, 0x10, 0xfe, 0xcc, 0x74, 0x63, 0x04, 0x72, 0xb6, 0xfa, + 0xef, 0xca, 0x4c, 0x23, 0x43, 0x78, 0x33, 0xd3, 0xc8, 0x30, 0xec, 0x24, 0xcf, 0x21, 0x8f, 0xb0, + 0x93, 0x64, 0xb5, 0x5f, 0x0d, 0x97, 0x9a, 0x59, 0x67, 0x62, 0x00, 0xaf, 0xfe, 0x0c, 0xaf, 0x29, + 0xf1, 0x09, 0x21, 0xfb, 0x82, 0xd2, 0x3e, 0x39, 0x9a, 0x37, 0x26, 0xe0, 0xec, 0xab, 0x57, 0xcf, + 0xef, 0x95, 0x09, 0xbe, 0xfb, 0x9d, 0xaf, 0x7e, 0xe8, 0x0b, 0x63, 0x08, 0x65, 0x1d, 0x7d, 0x10, + 0x3b, 0x43, 0x74, 0x0c, 0x70, 0x33, 0x1b, 0x13, 0xf3, 0x2b, 0x83, 0x5f, 0xe1, 0xdb, 0x6b, 0x10, + 0x99, 0x90, 0xb5, 0xcc, 0x70, 0x8c, 0xc5, 0x40, 0xe6, 0xed, 0xa9, 0x64, 0x94, 0x71, 0x47, 0x22, + 0x1f, 0x85, 0x6e, 0x48, 0xf6, 0x45, 0xde, 0x43, 0x48, 0xe6, 0x84, 0x7c, 0x2b, 0xc6, 0x2d, 0x03, + 0xcf, 0x19, 0x22, 0xde, 0x4c, 0xdd, 0xda, 0x53, 0x20, 0xf3, 0x9c, 0xe9, 0xd0, 0x79, 0xa3, 0xfc, + 0xdd, 0x9b, 0x2b, 0xc6, 0x3f, 0xde, 0x5c, 0x31, 0xfe, 0xf5, 0xe6, 0x8a, 0x71, 0x54, 0x10, 0x7f, + 0xa4, 0xde, 0xfe, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbd, 0xc1, 0x5b, 0x4b, 0xd1, 0x1e, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -4014,6 +4031,20 @@ func (m *ResolveImageConfigRequest) MarshalToSizedBuffer(dAtA []byte) (int, erro i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.SourcePolicies) > 0 { + for iNdEx := len(m.SourcePolicies) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SourcePolicies[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGateway(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + } if len(m.StoreID) > 0 { i -= len(m.StoreID) copy(dAtA[i:], m.StoreID) @@ -4093,6 +4124,13 @@ func (m *ResolveImageConfigResponse) MarshalToSizedBuffer(dAtA []byte) (int, err i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.Ref) > 0 { + i -= len(m.Ref) + copy(dAtA[i:], m.Ref) + i = encodeVarintGateway(dAtA, i, uint64(len(m.Ref))) + i-- + dAtA[i] = 0x1a + } if len(m.Config) > 0 { i -= len(m.Config) copy(dAtA[i:], m.Config) @@ -5958,6 +5996,12 @@ func (m *ResolveImageConfigRequest) Size() (n int) { if l > 0 { n += 1 + l + sovGateway(uint64(l)) } + if len(m.SourcePolicies) > 0 { + for _, e := range m.SourcePolicies { + l = e.Size() + n += 1 + l + sovGateway(uint64(l)) + } + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -5978,6 +6022,10 @@ func (m *ResolveImageConfigResponse) Size() (n int) { if l > 0 { n += 1 + l + sovGateway(uint64(l)) } + l = len(m.Ref) + if l > 0 { + n += 1 + l + sovGateway(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -8800,6 +8848,40 @@ func (m *ResolveImageConfigRequest) Unmarshal(dAtA []byte) error { } m.StoreID = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SourcePolicies", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGateway + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGateway + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGateway + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SourcePolicies = append(m.SourcePolicies, &pb1.Policy{}) + if err := m.SourcePolicies[len(m.SourcePolicies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGateway(dAtA[iNdEx:]) @@ -8917,6 +8999,38 @@ func (m *ResolveImageConfigResponse) Unmarshal(dAtA []byte) error { m.Config = []byte{} } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGateway + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGateway + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGateway + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ref = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGateway(dAtA[iNdEx:]) diff --git a/frontend/gateway/pb/gateway.proto b/frontend/gateway/pb/gateway.proto index 2e55f1db8688..bf4a0c334ccb 100644 --- a/frontend/gateway/pb/gateway.proto +++ b/frontend/gateway/pb/gateway.proto @@ -124,11 +124,13 @@ message ResolveImageConfigRequest { int32 ResolverType = 5; string SessionID = 6; string StoreID = 7; + repeated moby.buildkit.v1.sourcepolicy.Policy SourcePolicies = 8; } message ResolveImageConfigResponse { string Digest = 1 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false]; bytes Config = 2; + string Ref = 3; } message SolveRequest { diff --git a/solver/llbsolver/bridge.go b/solver/llbsolver/bridge.go index 185fe81f0649..61ad5636fa04 100644 --- a/solver/llbsolver/bridge.go +++ b/solver/llbsolver/bridge.go @@ -290,10 +290,10 @@ func (rp *resultProxy) Result(ctx context.Context) (res solver.CachedResult, err return nil, err } -func (b *llbBridge) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (dgst digest.Digest, config []byte, err error) { +func (b *llbBridge) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (resolvedRef string, dgst digest.Digest, config []byte, err error) { w, err := b.resolveWorker() if err != nil { - return "", nil, err + return "", "", nil, err } if opt.LogName == "" { opt.LogName = fmt.Sprintf("resolve image config for %s", ref) @@ -304,11 +304,18 @@ func (b *llbBridge) ResolveImageConfig(ctx context.Context, ref string, opt llb. } else { id += platforms.Format(*platform) } + pol, err := loadSourcePolicy(b.builder) + if err != nil { + return "", "", nil, err + } + if pol != nil { + opt.SourcePolicies = append(opt.SourcePolicies, pol) + } err = inBuilderContext(ctx, b.builder, opt.LogName, id, func(ctx context.Context, g session.Group) error { - dgst, config, err = w.ResolveImageConfig(ctx, ref, opt, b.sm, g) + resolvedRef, dgst, config, err = w.ResolveImageConfig(ctx, ref, opt, b.sm, g) return err }) - return dgst, config, err + return resolvedRef, dgst, config, err } type lazyCacheManager struct { diff --git a/solver/llbsolver/provenance.go b/solver/llbsolver/provenance.go index b30581c852d9..0815afd0dd1f 100644 --- a/solver/llbsolver/provenance.go +++ b/solver/llbsolver/provenance.go @@ -130,10 +130,10 @@ func (b *provenanceBridge) findByResult(rp solver.ResultProxy) (*resultWithBridg return nil, false } -func (b *provenanceBridge) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (dgst digest.Digest, config []byte, err error) { - dgst, config, err = b.llbBridge.ResolveImageConfig(ctx, ref, opt) +func (b *provenanceBridge) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (resolvedRef string, dgst digest.Digest, config []byte, err error) { + ref, dgst, config, err = b.llbBridge.ResolveImageConfig(ctx, ref, opt) if err != nil { - return "", nil, err + return "", "", nil, err } b.images = append(b.images, provenance.ImageSource{ @@ -141,7 +141,7 @@ func (b *provenanceBridge) ResolveImageConfig(ctx context.Context, ref string, o Platform: opt.Platform, Digest: dgst, }) - return dgst, config, nil + return ref, dgst, config, nil } func (b *provenanceBridge) Solve(ctx context.Context, req frontend.SolveRequest, sid string) (res *frontend.Result, err error) { diff --git a/source/containerimage/pull.go b/source/containerimage/pull.go index 509d2a994660..9f6b0d8e1760 100644 --- a/source/containerimage/pull.go +++ b/source/containerimage/pull.go @@ -82,8 +82,9 @@ func (is *Source) ID() string { return srctypes.DockerImageScheme } -func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager, g session.Group) (digest.Digest, []byte, error) { +func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager, g session.Group) (string, digest.Digest, []byte, error) { type t struct { + ref string dgst digest.Digest dt []byte } @@ -102,7 +103,7 @@ func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt llb.Re case ResolverTypeRegistry: rm, err = source.ParseImageResolveMode(opt.ResolveMode) if err != nil { - return "", nil, err + return "", "", nil, err } rslvr = resolver.DefaultPool.GetResolver(is.RegistryHosts, ref, "pull", sm, g).WithImageStore(is.ImageStore, rm) case ResolverTypeOCILayout: @@ -111,17 +112,17 @@ func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt llb.Re } key += rm.String() res, err := is.g.Do(ctx, key, func(ctx context.Context) (interface{}, error) { - dgst, dt, err := imageutil.Config(ctx, ref, rslvr, is.ContentStore, is.LeaseManager, opt.Platform) + newRef, dgst, dt, err := imageutil.Config(ctx, ref, rslvr, is.ContentStore, is.LeaseManager, opt.Platform, opt.SourcePolicies) if err != nil { return nil, err } - return &t{dgst: dgst, dt: dt}, nil + return &t{dgst: dgst, dt: dt, ref: newRef}, nil }) if err != nil { - return "", nil, err + return "", "", nil, err } typed = res.(*t) - return typed.dgst, typed.dt, nil + return typed.ref, typed.dgst, typed.dt, nil } func (is *Source) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager, vtx solver.Vertex) (source.SourceInstance, error) { diff --git a/sourcepolicy/engine.go b/sourcepolicy/engine.go index 829e8510650c..8515b276a416 100644 --- a/sourcepolicy/engine.go +++ b/sourcepolicy/engine.go @@ -7,6 +7,7 @@ import ( spb "github.com/moby/buildkit/sourcepolicy/pb" "github.com/moby/buildkit/util/bklog" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) var ( @@ -112,12 +113,20 @@ func (e *Engine) evaluatePolicies(ctx context.Context, srcOp *pb.SourceOp) (bool // // For Allow/Deny rules, the last matching rule wins. // E.g. `ALLOW foo; DENY foo` will deny `foo`, `DENY foo; ALLOW foo` will allow `foo`. -func (e *Engine) evaluatePolicy(ctx context.Context, pol *spb.Policy, srcOp *pb.SourceOp) (bool, error) { +func (e *Engine) evaluatePolicy(ctx context.Context, pol *spb.Policy, srcOp *pb.SourceOp) (retMut bool, retErr error) { ident := srcOp.GetIdentifier() - ctx = bklog.WithLogger(ctx, bklog.G(ctx).WithFields(map[string]interface{}{ - "ref": ident, - })) + ctx = bklog.WithLogger(ctx, bklog.G(ctx).WithField("ref", ident)) + defer func() { + if retMut || retErr != nil { + bklog.G(ctx).WithFields( + logrus.Fields{ + "mutated": retMut, + "updated": srcOp.GetIdentifier(), + logrus.ErrorKey: retErr, + }).Debug("Evaluated source policy") + } + }() var deny bool for _, rule := range pol.Rules { diff --git a/util/imageutil/config.go b/util/imageutil/config.go index 76e0a5da350c..168dc6dc7684 100644 --- a/util/imageutil/config.go +++ b/util/imageutil/config.go @@ -3,6 +3,8 @@ package imageutil import ( "context" "encoding/json" + "fmt" + "strings" "sync" "time" @@ -13,6 +15,10 @@ import ( "github.com/containerd/containerd/reference" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" + "github.com/moby/buildkit/solver/pb" + srctypes "github.com/moby/buildkit/source/types" + "github.com/moby/buildkit/sourcepolicy" + spb "github.com/moby/buildkit/sourcepolicy/pb" "github.com/moby/buildkit/util/attestation" "github.com/moby/buildkit/util/contentutil" "github.com/moby/buildkit/util/leaseutil" @@ -47,7 +53,17 @@ func AddLease(f func(context.Context) error) { leasesMu.Unlock() } -func Config(ctx context.Context, str string, resolver remotes.Resolver, cache ContentCache, leaseManager leases.Manager, p *ocispecs.Platform) (digest.Digest, []byte, error) { +// ResolveToNonImageError is returned by the resolver when the ref is mutated by policy to a non-image ref +type ResolveToNonImageError struct { + Ref string + Updated string +} + +func (e ResolveToNonImageError) Error() string { + return fmt.Sprintf("ref mutated by policy to non-image: %s://%s -> %s", srctypes.DockerImageScheme, e.Ref, e.Updated) +} + +func Config(ctx context.Context, str string, resolver remotes.Resolver, cache ContentCache, leaseManager leases.Manager, p *ocispecs.Platform, spls []*spb.Policy) (string, digest.Digest, []byte, error) { // TODO: fix buildkit to take interface instead of struct var platform platforms.MatchComparer if p != nil { @@ -57,13 +73,44 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, cache Co } ref, err := reference.Parse(str) if err != nil { - return "", nil, errors.WithStack(err) + return "", "", nil, errors.WithStack(err) + } + + op := &pb.Op{ + Op: &pb.Op_Source{ + Source: &pb.SourceOp{ + Identifier: srctypes.DockerImageScheme + "://" + ref.String(), + }, + }, + } + + mut, err := sourcepolicy.NewEngine(spls).Evaluate(ctx, op) + if err != nil { + return "", "", nil, errors.Wrap(err, "could not resolve image due to policy") + } + + if mut { + var ( + t string + ok bool + ) + t, newRef, ok := strings.Cut(op.GetSource().GetIdentifier(), "://") + if !ok { + return "", "", nil, errors.Errorf("could not parse ref: %s", op.GetSource().GetIdentifier()) + } + if ok && t != srctypes.DockerImageScheme { + return "", "", nil, &ResolveToNonImageError{Ref: str, Updated: newRef} + } + ref, err = reference.Parse(newRef) + if err != nil { + return "", "", nil, errors.WithStack(err) + } } if leaseManager != nil { ctx2, done, err := leaseutil.WithLease(ctx, leaseManager, leases.WithExpiration(5*time.Minute), leaseutil.MakeTemporary) if err != nil { - return "", nil, errors.WithStack(err) + return "", "", nil, errors.WithStack(err) } ctx = ctx2 defer func() { @@ -94,24 +141,25 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, cache Co if desc.MediaType == "" { _, desc, err = resolver.Resolve(ctx, ref.String()) if err != nil { - return "", nil, err + return "", "", nil, err } } fetcher, err := resolver.Fetcher(ctx, ref.String()) if err != nil { - return "", nil, err + return "", "", nil, err } if desc.MediaType == images.MediaTypeDockerSchema1Manifest { - return readSchema1Config(ctx, ref.String(), desc, fetcher, cache) + dgst, dt, err := readSchema1Config(ctx, ref.String(), desc, fetcher, cache) + return ref.String(), dgst, dt, err } children := childrenConfigHandler(cache, platform) dslHandler, err := docker.AppendDistributionSourceLabel(cache, ref.String()) if err != nil { - return "", nil, err + return "", "", nil, err } handlers := []images.Handler{ @@ -120,19 +168,19 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, cache Co children, } if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil { - return "", nil, err + return "", "", nil, err } config, err := images.Config(ctx, cache, desc, platform) if err != nil { - return "", nil, err + return "", "", nil, err } dt, err := content.ReadBlob(ctx, cache, config) if err != nil { - return "", nil, err + return "", "", nil, err } - return desc.Digest, dt, nil + return ref.String(), desc.Digest, dt, nil } func childrenConfigHandler(provider content.Provider, platform platforms.MatchComparer) images.HandlerFunc { diff --git a/worker/base/worker.go b/worker/base/worker.go index 2c3e4defd17f..32a826f8840b 100644 --- a/worker/base/worker.go +++ b/worker/base/worker.go @@ -354,7 +354,7 @@ func (w *Worker) PruneCacheMounts(ctx context.Context, ids []string) error { return nil } -func (w *Worker) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager, g session.Group) (digest.Digest, []byte, error) { +func (w *Worker) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager, g session.Group) (string, digest.Digest, []byte, error) { // is this an registry source? Or an OCI layout source? switch opt.ResolverType { case llb.ResolverTypeOCILayout: diff --git a/worker/worker.go b/worker/worker.go index 2f426e9ead40..83b3f6671778 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -30,7 +30,7 @@ type Worker interface { LoadRef(ctx context.Context, id string, hidden bool) (cache.ImmutableRef, error) // ResolveOp resolves Vertex.Sys() to Op implementation. ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge, sm *session.Manager) (solver.Op, error) - ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager, g session.Group) (digest.Digest, []byte, error) + ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager, g session.Group) (string, digest.Digest, []byte, error) DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error) Exporter(name string, sm *session.Manager) (exporter.Exporter, error) Prune(ctx context.Context, ch chan client.UsageInfo, opt ...client.PruneInfo) error From aa4340b9aebf32380d31f2b8f9fdf48f42208fae Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Tue, 11 Jul 2023 22:46:10 -0700 Subject: [PATCH 2/2] llbsolver: fix policy rule ordering The older of rules in policy matters. Eg. in [DENY *, ALLOW ref] mixing the order would deny all sources so map can't be used to deduplicate the rules. Signed-off-by: Tonis Tiigi (cherry picked from commit 22d84461e4ed2e861c15ee1a1695dc75da27a9e3) Signed-off-by: Brian Goff --- solver/llbsolver/solver.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/solver/llbsolver/solver.go b/solver/llbsolver/solver.go index d65a9e6490c7..94d25ce5b7b2 100644 --- a/solver/llbsolver/solver.go +++ b/solver/llbsolver/solver.go @@ -977,27 +977,21 @@ func loadEntitlements(b solver.Builder) (entitlements.Set, error) { } func loadSourcePolicy(b solver.Builder) (*spb.Policy, error) { - set := make(map[spb.Rule]struct{}, 0) + var srcPol spb.Policy err := b.EachValue(context.TODO(), keySourcePolicy, func(v interface{}) error { x, ok := v.(spb.Policy) if !ok { return errors.Errorf("invalid source policy %T", v) } for _, f := range x.Rules { - set[*f] = struct{}{} + r := *f + srcPol.Rules = append(srcPol.Rules, &r) } + srcPol.Version = x.Version return nil }) if err != nil { return nil, err } - var srcPol *spb.Policy - if len(set) > 0 { - srcPol = &spb.Policy{} - for k := range set { - k := k - srcPol.Rules = append(srcPol.Rules, &k) - } - } - return srcPol, nil + return &srcPol, nil }