Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: honour --ttl flag in 'ipfs name publish' #9471

Merged
merged 2 commits into from
Jan 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/commands/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ func TestCommands(t *testing.T) {
"/multibase/transcode",
"/multibase/list",
"/name",
"/name/inspect",
"/name/publish",
"/name/pubsub",
"/name/pubsub/cancel",
Expand Down
219 changes: 218 additions & 1 deletion core/commands/name/name.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
package name

import (
"github.com/ipfs/go-ipfs-cmds"
"bytes"
"encoding/json"
"fmt"
"io"
"strings"
"text/tabwriter"
"time"

"github.com/gogo/protobuf/proto"
cmds "github.com/ipfs/go-ipfs-cmds"
"github.com/ipfs/go-ipns"
ipns_pb "github.com/ipfs/go-ipns/pb"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/codec/dagcbor"
"github.com/ipld/go-ipld-prime/codec/dagjson"
ic "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
mbase "github.com/multiformats/go-multibase"
)

type IpnsEntry struct {
Expand Down Expand Up @@ -62,5 +80,204 @@ Resolve the value of a dnslink:
"publish": PublishCmd,
"resolve": IpnsCmd,
"pubsub": IpnsPubsubCmd,
"inspect": IpnsInspectCmd,
},
}

type IpnsInspectValidation struct {
Valid bool
Reason string
PublicKey peer.ID
}

// IpnsInspectEntry contains the deserialized values from an IPNS Entry:
// https://github.com/ipfs/specs/blob/main/ipns/IPNS.md#record-serialization-format
type IpnsInspectEntry struct {
Value string
ValidityType *ipns_pb.IpnsEntry_ValidityType
Validity *time.Time
Sequence uint64
TTL *uint64
PublicKey string
SignatureV1 string
SignatureV2 string
Data interface{}
}

type IpnsInspectResult struct {
Entry IpnsInspectEntry
Validation *IpnsInspectValidation
}

var IpnsInspectCmd = &cmds.Command{
Status: cmds.Experimental,
hacdias marked this conversation as resolved.
Show resolved Hide resolved
Helptext: cmds.HelpText{
Tagline: "Inspects an IPNS Record",
ShortDescription: `
Prints values inside of IPNS Record protobuf and its DAG-CBOR Data field.
Passing --verify will verify signature against provided public key.
`,
LongDescription: `
Prints values inside of IPNS Record protobuf and its DAG-CBOR Data field.

The input can be a file or STDIN, the output can be JSON:

$ ipfs routing get "/ipns/$PEERID" > ipns_record
$ ipfs name inspect --enc=json < ipns_record

Values in PublicKey, SignatureV1 and SignatureV2 fields are raw bytes encoded
in Multibase. The Data field is DAG-CBOR represented as DAG-JSON.

Passing --verify will verify signature against provided public key.

`,
},
Arguments: []cmds.Argument{
cmds.FileArg("record", true, false, "The IPNS record payload to be verified.").EnableStdin(),
},
Options: []cmds.Option{
cmds.StringOption("verify", "CID of the public IPNS key to validate against."),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
file, err := cmdenv.GetFileArg(req.Files.Entries())
if err != nil {
return err
}
defer file.Close()

var b bytes.Buffer

_, err = io.Copy(&b, file)
if err != nil {
return err
}

var entry ipns_pb.IpnsEntry
err = proto.Unmarshal(b.Bytes(), &entry)
if err != nil {
return err
}

encoder, err := mbase.EncoderByName("base64")
if err != nil {
return err
}

result := &IpnsInspectResult{
Entry: IpnsInspectEntry{
Value: string(entry.Value),
ValidityType: entry.ValidityType,
Sequence: *entry.Sequence,
TTL: entry.Ttl,
PublicKey: encoder.Encode(entry.PubKey),
SignatureV1: encoder.Encode(entry.SignatureV1),
SignatureV2: encoder.Encode(entry.SignatureV2),
Data: nil,
},
}

if len(entry.Data) != 0 {
// This is hacky. The variable node (datamodel.Node) doesn't directly marshal
// to JSON. Therefore, we need to first decode from DAG-CBOR, then encode in
// DAG-JSON and finally unmarshal it from JSON. Since DAG-JSON is a subset
// of JSON, that should work. Then, we can store the final value in the
// result.Entry.Data for further inspection.
node, err := ipld.Decode(entry.Data, dagcbor.Decode)
if err != nil {
return err
}

var buf bytes.Buffer
err = dagjson.Encode(node, &buf)
if err != nil {
return err
}

err = json.Unmarshal(buf.Bytes(), &result.Entry.Data)
if err != nil {
return err
}
}

validity, err := ipns.GetEOL(&entry)
if err == nil {
result.Entry.Validity = &validity
}

verify, ok := req.Options["verify"].(string)
if ok {
key := strings.TrimPrefix(verify, "/ipns/")
id, err := peer.Decode(key)
if err != nil {
return err
}

result.Validation = &IpnsInspectValidation{
PublicKey: id,
}

pub, err := id.ExtractPublicKey()
if err != nil {
// Make sure it works with all those RSA that cannot be embedded into the
// Peer ID.
if len(entry.PubKey) > 0 {
pub, err = ic.UnmarshalPublicKey(entry.PubKey)
}
}
if err != nil {
return err
}

err = ipns.Validate(pub, &entry)
if err == nil {
result.Validation.Valid = true
} else {
result.Validation.Reason = err.Error()
}
}

return cmds.EmitOnce(res, result)
},
Type: IpnsInspectResult{},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *IpnsInspectResult) error {
tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0)
defer tw.Flush()

fmt.Fprintf(tw, "Value:\t%q\n", string(out.Entry.Value))
fmt.Fprintf(tw, "Validity Type:\t%q\n", out.Entry.ValidityType)
if out.Entry.Validity != nil {
fmt.Fprintf(tw, "Validity:\t%s\n", out.Entry.Validity.Format(time.RFC3339Nano))
}
fmt.Fprintf(tw, "Sequence:\t%d\n", out.Entry.Sequence)
if out.Entry.TTL != nil {
fmt.Fprintf(tw, "TTL:\t%d\n", *out.Entry.TTL)
}
fmt.Fprintf(tw, "PublicKey:\t%q\n", out.Entry.PublicKey)
fmt.Fprintf(tw, "Signature V1:\t%q\n", out.Entry.SignatureV1)
fmt.Fprintf(tw, "Signature V2:\t%q\n", out.Entry.SignatureV2)

data, err := json.Marshal(out.Entry.Data)
if err != nil {
return err
}
fmt.Fprintf(tw, "Data:\t%s\n", string(data))

if out.Validation == nil {
tw.Flush()
fmt.Fprintf(w, "\nThis record was not validated.\n")
} else {
tw.Flush()
fmt.Fprintf(w, "\nValidation results:\n")

fmt.Fprintf(tw, "\tValid:\t%v\n", out.Validation.Valid)
if out.Validation.Reason != "" {
fmt.Fprintf(tw, "\tReason:\t%s\n", out.Validation.Reason)
}
fmt.Fprintf(tw, "\tPublicKey:\t%s\n", out.Validation.PublicKey)
}

return nil
}),
},
}
15 changes: 9 additions & 6 deletions core/coreapi/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
ipath "github.com/ipfs/go-path"
coreiface "github.com/ipfs/interface-go-ipfs-core"
caopts "github.com/ipfs/interface-go-ipfs-core/options"
nsopts "github.com/ipfs/interface-go-ipfs-core/options/namesys"
path "github.com/ipfs/interface-go-ipfs-core/path"
ci "github.com/libp2p/go-libp2p/core/crypto"
peer "github.com/libp2p/go-libp2p/core/peer"
Expand All @@ -37,8 +38,6 @@ func (e *ipnsEntry) Value() path.Path {
return e.value
}

type requestContextKey string

// Publish announces new IPNS name and returns the new IPNS entry.
func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.NamePublishOption) (coreiface.IpnsEntry, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.NameAPI", "Publish", trace.WithAttributes(attribute.String("path", p.String())))
Expand Down Expand Up @@ -76,13 +75,17 @@ func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.Nam
return nil, err
}

eol := time.Now().Add(options.ValidTime)

publishOptions := []nsopts.PublishOption{
nsopts.PublishWithEOL(eol),
}

if options.TTL != nil {
// nolint: staticcheck // non-backward compatible change
ctx = context.WithValue(ctx, requestContextKey("ipns-publish-ttl"), *options.TTL)
publishOptions = append(publishOptions, nsopts.PublishWithTTL(*options.TTL))
}

eol := time.Now().Add(options.ValidTime)
err = api.namesys.PublishWithEOL(ctx, k, pth, eol)
err = api.namesys.Publish(ctx, k, pth, publishOptions...)
if err != nil {
return nil, err
}
Expand Down
7 changes: 1 addition & 6 deletions core/corehttp/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"regexp"
"strings"
"testing"
"time"

namesys "github.com/ipfs/go-namesys"
version "github.com/ipfs/kubo"
Expand Down Expand Up @@ -68,11 +67,7 @@ func (m mockNamesys) ResolveAsync(ctx context.Context, name string, opts ...nsop
return out
}

func (m mockNamesys) Publish(ctx context.Context, name ci.PrivKey, value path.Path) error {
return errors.New("not implemented for mockNamesys")
}

func (m mockNamesys) PublishWithEOL(ctx context.Context, name ci.PrivKey, value path.Path, _ time.Time) error {
func (m mockNamesys) Publish(ctx context.Context, name ci.PrivKey, value path.Path, opts ...nsopts.PublishOption) error {
return errors.New("not implemented for mockNamesys")
}

Expand Down
8 changes: 4 additions & 4 deletions docs/examples/kubo-as-a-library/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ replace github.com/ipfs/kubo => ./../../..

require (
github.com/ipfs/go-libipfs v0.3.0
github.com/ipfs/interface-go-ipfs-core v0.8.2
github.com/ipfs/kubo v0.14.0-rc1
github.com/ipfs/interface-go-ipfs-core v0.9.0
github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
github.com/libp2p/go-libp2p v0.24.2
github.com/multiformats/go-multiaddr v0.8.0
)
Expand Down Expand Up @@ -100,7 +100,7 @@ require (
github.com/ipfs/go-merkledag v0.9.0 // indirect
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
github.com/ipfs/go-mfs v0.2.1 // indirect
github.com/ipfs/go-namesys v0.6.0 // indirect
github.com/ipfs/go-namesys v0.7.0 // indirect
github.com/ipfs/go-path v0.3.0 // indirect
github.com/ipfs/go-peertaskqueue v0.8.0 // indirect
github.com/ipfs/go-unixfs v0.4.2 // indirect
Expand Down Expand Up @@ -209,7 +209,7 @@ require (
golang.org/x/tools v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect
google.golang.org/grpc v1.47.0 // indirect
google.golang.org/grpc v1.46.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
lukechampine.com/blake3 v1.1.7 // indirect
Expand Down
11 changes: 5 additions & 6 deletions docs/examples/kubo-as-a-library/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -573,8 +573,8 @@ github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fG
github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY=
github.com/ipfs/go-mfs v0.2.1 h1:5jz8+ukAg/z6jTkollzxGzhkl3yxm022Za9f2nL5ab8=
github.com/ipfs/go-mfs v0.2.1/go.mod h1:Woj80iuw4ajDnIP6+seRaoHpPsc9hmL0pk/nDNDWP88=
github.com/ipfs/go-namesys v0.6.0 h1:w4+Wq9bCILnuZRT1RBBdzZQFqtJeDG1duzN8mIDnHZ0=
github.com/ipfs/go-namesys v0.6.0/go.mod h1:0L+3CHBgHxr08Cg+chVo9Ew285PGQfToThjll4g0/d4=
github.com/ipfs/go-namesys v0.7.0 h1:xqosk71GIVRkFDtF2UNRcXn4LdNeo7tzuy8feHD6NbU=
github.com/ipfs/go-namesys v0.7.0/go.mod h1:KYSZBVZG3VJC34EfqqJPG7T48aWgxseoMPAPA5gLyyQ=
github.com/ipfs/go-path v0.2.1/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I=
github.com/ipfs/go-path v0.3.0 h1:tkjga3MtpXyM5v+3EbRvOHEoo+frwi4oumw5K+KYWyA=
github.com/ipfs/go-path v0.3.0/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I=
Expand All @@ -592,8 +592,8 @@ github.com/ipfs/go-unixfsnode v1.5.1/go.mod h1:ed79DaG9IEuZITJVQn4U6MZDftv6I3ygU
github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0=
github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs=
github.com/ipfs/go-verifcid v0.0.2/go.mod h1:40cD9x1y4OWnFXbLNJYRe7MpNvWlMn3LZAG5Wb4xnPU=
github.com/ipfs/interface-go-ipfs-core v0.8.2 h1:WDeCBnE4MENVOXbtfwwdAPJ2nBBS8PTmhZWWpm24HRM=
github.com/ipfs/interface-go-ipfs-core v0.8.2/go.mod h1:F3EcmDy53GFkF0H3iEJpfJC320fZ/4G60eftnItrrJ0=
github.com/ipfs/interface-go-ipfs-core v0.9.0 h1:+RCouVtSU/SldgkqWufjIu1smmGaSyKgUIfbYwLukgI=
github.com/ipfs/interface-go-ipfs-core v0.9.0/go.mod h1:F3EcmDy53GFkF0H3iEJpfJC320fZ/4G60eftnItrrJ0=
github.com/ipld/edelweiss v0.2.0 h1:KfAZBP8eeJtrLxLhi7r3N0cBCo7JmwSRhOJp3WSpNjk=
github.com/ipld/edelweiss v0.2.0/go.mod h1:FJAzJRCep4iI8FOFlRriN9n0b7OuX3T/S9++NpBDmA4=
github.com/ipld/go-car v0.4.0 h1:U6W7F1aKF/OJMHovnOVdst2cpQE5GhmHibQkAixgNcQ=
Expand Down Expand Up @@ -1779,9 +1779,8 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
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=
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5
github.com/fsnotify/fsnotify v1.6.0
github.com/gabriel-vasile/mimetype v1.4.1
github.com/gogo/protobuf v1.3.2
github.com/google/uuid v1.3.0
github.com/hashicorp/go-multierror v1.1.1
github.com/ipfs/go-bitswap v0.11.0
Expand Down Expand Up @@ -55,13 +56,13 @@ require (
github.com/ipfs/go-metrics-interface v0.0.1
github.com/ipfs/go-metrics-prometheus v0.0.2
github.com/ipfs/go-mfs v0.2.1
github.com/ipfs/go-namesys v0.6.0
github.com/ipfs/go-namesys v0.7.0
github.com/ipfs/go-path v0.3.0
github.com/ipfs/go-pinning-service-http-client v0.1.2
github.com/ipfs/go-unixfs v0.4.2
github.com/ipfs/go-unixfsnode v1.5.1
github.com/ipfs/go-verifcid v0.0.2
github.com/ipfs/interface-go-ipfs-core v0.8.2
github.com/ipfs/interface-go-ipfs-core v0.9.0
github.com/ipld/go-car v0.4.0
github.com/ipld/go-car/v2 v2.5.1
github.com/ipld/go-codec-dagpb v1.5.0
Expand Down Expand Up @@ -141,7 +142,6 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
Expand Down
Loading