82 Commits
Author SHA1 Message Date
Will NorrisandWill Norris 55a3c6e2fe use semantic version tagging for docker images
we've never tagged stable releases, but should really do so.  This
change will cause our docker images to be tagged following typical
semver fashion... the initial `v1.0.0` release will be tagged `v1`,
`v1.0`, `v1.0.0`, and `latest`.

Updates #104

Signed-off-by: Will Norris <will@tailscale.com>
2024-05-08 16:33:21 -07:00
Will NorrisandWill Norris 187497a7ce add regexp.Match to template funcs
Add a "Match" template func, which uses regexp.MatchString to match a
value against a regular expression pattern.

Fixes #125

Signed-off-by: Will Norris <will@tailscale.com>
2024-05-07 12:18:56 -07:00
Will NorrisandWill Norris e2c7c78ae1 README: document permission model and grants
Updates #18
Updates #22
Updates #86
Updates #120

Signed-off-by: Will Norris <will@tailscale.com>
2024-04-02 11:39:56 -07:00
Will NorrisandWill Norris 6c79b503e1 suggest long URL for new go links if peer exists
If you visit a non-existent go link, we render the home page and pre-
populate the "short" input with the name of the link, and autofocus the
"long" input so that you can simply paste a long URL and submit.

It is common (at least at Tailscale) to create go links that correspond
to the name of a device on the tailnet.  For example, go/who points to
http://who/.  With this change, when you visit a non-existent go link,
we check to see if a peer exists on the tailnet with that name, and if
so we suggest that as the long URL.

Signed-off-by: Will Norris <will@tailscale.com>
2024-03-15 14:42:43 -07:00
Will NorrisandWill Norris 0b61ec165e make https optional (but default to on)
Fixes #107

Signed-off-by: Will Norris <will@tailscale.com>
2024-03-04 11:26:20 -08:00
Will NorrisandWill Norris 544870985e enable new web ui for managing node
we've had support for enabling the web UI in tsnet apps from the
beginning, but I don't think we've ever actually used it anywhere.
some of the settings exposed through the web ui don't make a ton of
sense for tsnet, and might not even work.  But we're working toward
being able to enable the web ui on clients by default (with all of the
existing restrictions and ACL enforcement in place), and golink seemed
like a good playground to try it in a tsnet app.

Signed-off-by: Will Norris <will@tailscale.com>
2024-03-04 10:04:19 -08:00
Will NorrisandWill Norris b76177ac91 go.mod: use latest stable build of tailscale
We have fixed the issue in the corp repo that required us to use
pseudo-versions for the tailscale.com module here. So we can now switch
to the latest stable version.

Signed-off-by: Will Norris <will@tailscale.com>
2024-03-01 12:01:05 -08:00
Will NorrisandWill Norris 9583fd9c67 go.mod: bump to tailscale 1.60.0
Commit 256ecd0e8f7cc7ccc1a20e3f2846f6e3cc336d02 was the latest actual
commit before tagging v1.60.0

Signed-off-by: Will Norris <will@tailscale.com>
2024-02-28 17:00:00 -08:00
Will NorrisandWill Norris 0abea01a93 golink: align on tailscale.com/cap naming convention
Signed-off-by: Will Norris <will@tailscale.com>
2023-12-13 09:09:57 -08:00
Will NorrisandWill Norris c9212a47de .github: update actions in docker workflow
Signed-off-by: Will Norris <will@tailscale.com>
2023-11-15 08:26:40 -08:00
Will NorrisandWill Norris c4bacfd78c .github: run yaml files through prettier
Signed-off-by: Will Norris <will@tailscale.com>
2023-11-15 08:26:40 -08:00
Will NorrisandWill Norris 7f89e2e42c golink: set HTTP status after Location header
I didn't think the order mattered (as long as none of the response body
had been written), but I guess I was wrong. Currently, it's returning
the 302 status, but no Location header. And tests, at least some of
which should be passing through this full code path, are passing. I'll
look into adding better testing later, but for now this fixes the
immediate issue.

Updates #91

Signed-off-by: Will Norris <will@tailscale.com>
2023-11-14 21:42:41 -08:00
Will NorrisandWill Norris 7db43e2d37 golink: use new serveHandler with tsnet
In 46ed42f, I mistakenly only attached the serveHandler to the dev
listener, but not tsnet.

Fixes #91

Signed-off-by: Will Norris <will@tailscale.com>
2023-11-14 20:18:12 -08:00
Will NorrisandWill Norris 46ed42fc5d golink: don't modify URL path when resolving link
Both http.ServeMux as well as the http.Redirect method pass the request
URL through `cleanPath` which, among other things, collapses double
slashes `//` to a single slash `/`. Most of the time this is fine, since
most servers treat those as identical anyway. But some destination
servers need the original path unmodified. Since we're just redirecting,
we don't need to be concerned with the additional benefits of
`cleanPath` such as eliminating `../` path components, since that is the
responsibility of the destination server to clean if needed.

This change adds a separate root http.Handler for golink requests. It
still uses http.ServeMux for internal endpoints, but serves golinks
directly without passing the request through ServeMux. Additionally,
this sets the redirect status and Location header directly rather than
calling http.Redirect, since that also modifies the URL it is given.

Fixes #89

Signed-off-by: Will Norris <will@tailscale.com>
2023-11-14 08:38:17 -08:00
Will NorrisandWill Norris 2ff7d040f8 add support for golink peer capability
The "tailscale.com/golink" peercap includes a single "admin" bool field.
When set, this grants the user the ability to edit all links stored in
the system.

Update currentUser to return a simple user struct instead of just a bare
username. Rename checkLinkOwnership to canEditLink and change to a bool
return value.

Signed-off-by: Will Norris <will@tailscale.com>
2023-10-30 20:29:58 -07:00
Will NorrisandWill Norris 97cee318a6 go.mod: bump to tailscale 1.52.0
Technically, this is one commit before the 1.52.0 tag to keep it a
pseudo-version.

Signed-off-by: Will Norris <will@tailscale.com>
2023-10-30 20:29:58 -07:00
Will NorrisandWill Norris 3d62a353ac Dockerfile: stop using chainguard go image
Chainguard is no longer allowing free users to use specific versions of
images like go (instead, having to always use "latest"). So instead, we
will create our own build image by installing the needed packages on top
of the wolfi-base image.

This is one of the recommended approaches in their migration guide:
https://www.chainguard.dev/unchained/a-guide-on-how-to-use-chainguard-images-for-public-catalog-tier-users

Fixes #82

Signed-off-by: Will Norris <will@tailscale.com>
2023-07-14 12:17:24 -07:00
Will NorrisandWill Norris a762273463 retain query string from original request
When resolving a go link, combine the query string parameters from the
request and long URL.

Updates #77

Signed-off-by: Will Norris <will@tailscale.com>
2023-05-16 10:17:35 -07:00
Will NorrisandWill Norris ae5d8c9b6c pass url.URL rather than string
return a *url.URL value from expandLink rather than a string, and both
accept and return a *url.URL value from resolveLink rather than a
string. These are both unexported funcs, so this has no changes to the
current behavior. It does prevent a few unnecessary conversions back and
forth between url.URL and string values, and will make it simpler to
retain request query strings.

Updates #77

Signed-off-by: Will Norris <will@tailscale.com>
2023-05-16 10:17:35 -07:00
Will NorrisandWill Norris f00de63b45 parse link short name just from request path
Previously, we were parsing from r.RequestURI, which includes both the
path and query string.  This causes problem for requests like go/who?q
which try to lookup a link named "who?q" rather than "who" (see #77).

For now, this just ignores the request query string. Eventually we
should probably retain the query string, but this begins by parsing out
the short name properly.

Updates #77

Signed-off-by: Will Norris <will@tailscale.com>
2023-05-16 10:17:35 -07:00
Will NorrisandWill Norris 41060ba068 go.mod: bump tailscale.com version
bump version again, back to the latest commit on main, rather than the
latest released version. Otherwise, this causes issues in tailscale's
corp repo (sadly).

Signed-off-by: Will Norris <will@tailscale.com>
2023-05-01 21:01:05 -07:00
Will NorrisandWill Norris ec2a3e94c6 go.mod: bump tailscale.com version
Signed-off-by: Will Norris <will@tailscale.com>
2023-05-01 20:55:34 -07:00
Will NorrisandWill Norris 61a86749e3 allow links to be saved without known owner
If the current user can't be determined (either because of a legitimate
error within the localapi client, or the user is coming through a subnet
router and doesn't have a Tailscale IP address), and the
-allow-unknown-users flag is set, then go ahead and save new links
without an owner.

By saving links without an owner, these unknown users can continue to
modify the link, and actual Tailscale users can take ownership. Once the
link is owned, it can no longer be modified by anyone other than the
owner.

Links that use the current user by having `{{ .User }}` in their long
URL cannot be resolved by unknown users and will return an error.

Fixes #60

Signed-off-by: Will Norris <will@tailscale.com>
2023-05-01 20:55:34 -07:00
Will NorrisandWill Norris 132a396390 update colors and tweak detail layout
Signed-off-by: Will Norris <will@tailscale.com>
2023-05-01 17:34:41 -07:00
Will NorrisandWill Norris 31b1ce1ac1 add tests for serve methods
Also check error returned from tmpl.Execute. Refactor currentUser to
make the logic a little simpler, and make it a package var for easier
testing.

Signed-off-by: Will Norris <will@tailscale.com>
2023-05-01 12:22:42 -07:00
Will NorrisandWill Norris b9fdc2dcab golink: allow -resolve-from-backup to resolve alias links
It's not uncommon to have multiple links pointing to the same
destination, for example to handle different spellings of a word or
because different people created them at different times.

A common best practice is to select one as the "primary" link and point
the others to that link as "aliases".  This change updates resolveLink
to follow those aliases so that the final destination is returned when
using `golink -resolve-from-backup`.

Signed-off-by: Will Norris <will@tailscale.com>
2023-03-29 13:55:38 -07:00
Will NorrisandWill Norris 7fd2d35ba6 include current user resolving link in expandEnv
Add "User" to the expansion environment for links.  The intent here it
support personalized go links such as:

go/mycal => https://calendar.google.com/calendar/embed?src={{.User}}

That's not a terribly interesting example, but there are others I intend
to use internally.

Signed-off-by: Will Norris <will@tailscale.com>
2023-02-08 16:24:36 -08:00
Will NorrisandWill Norris 9c46bb3412 stats: return early if no stats to write
Signed-off-by: Will Norris <will@tailscale.com>
2023-02-08 14:51:00 -08:00
Will NorrisandWill Norris 3c4fb78866 css: responsive design for /.all page
Signed-off-by: Will Norris <will@tailscale.com>
2023-02-07 16:08:19 -08:00
Will NorrisandWill Norris 396a3ae5a9 .github/workflow: use buildx v0.9.1 to fix fly deploys
Fixes #51

Signed-off-by: Will Norris <will@tailscale.com>
2023-02-01 13:20:01 -08:00
Will NorrisandWill Norris 3af59c51b8 Dockerfile: cross compile images using native builder
Use a build image built for the native architecture so that it doesn't
run in emulation mode.

Switch to Chainguard's wolfi/glibc build image. This limits our build
architectures to just amd64 and arm64, but that is sufficient for our
needs.

Updates #42
Updates #43

Signed-off-by: Will Norris <will@tailscale.com>
2023-01-09 20:32:47 -08:00
Will NorrisandWill Norris ef7f8b26d8 Dockerfile: use musl variant for go build image
Fixes #42

Signed-off-by: Will Norris <will@tailscale.com>
2023-01-07 10:42:53 -08:00
Will NorrisandWill Norris 406c48e54d skip "tagged-devices" in userExists check
Currently, the special "tagged-devices" user (which exists for any
tagged devices in the tailnet) can own go links.  This change permits
tagged devices to continue to create go links, but skips over them for
ownership checks, allowing any human user can take over ownership.

Fixes #37

Signed-off-by: Will Norris <will@tailscale.com>
2022-12-22 12:15:49 -08:00
Will NorrisandWill Norris b6f2ad4476 db: use canonical link short name in stats
When loading stats from the database, map IDs back to their canonical
short name, which is what we want to show in the frontend.  This is only
called once on cold start, so performance of loading all links isn't a
big concern.

Fixes #13

Signed-off-by: Will Norris <will@tailscale.com>
2022-12-21 10:52:23 -08:00
Will NorrisandWill Norris 5eb91a2ccf readme: add disambiguation links for other go link services
Signed-off-by: Will Norris <will@tailscale.com>
2022-12-14 12:12:31 -08:00
Will NorrisandWill Norris 7dd1eca5ce readme: add link to blog post
Signed-off-by: Will Norris <will@tailscale.com>
2022-12-13 21:33:10 -08:00
Will NorrisandWill Norris 5fefe2519f .github: cross-compile docker images
Build docker images for amd64, arm64, and arm/v7.  Also several other
small improvements to docker workflow like documenting which actions we
run on, setting concurrency settings, and reversing the logic for when
we push new images live (specifically looking for a push event rather
than a "not pull request" event, in case we add other events later).

Fixes #26
2022-12-06 20:33:21 -08:00
Will NorrisandWill Norris af7ceb5acb add support for resolving links locally
Specify a command line argument to resolve a link locally and exit.

Also add a new flag, -resolve-from-backup, which loads a snapshot into
an in-memory database and resolves the specified link.
2022-12-06 14:19:31 -08:00
Will NorrisandWill Norris 9d1e45fb4e add basic favicon
Nothing fancy, just the text "go/" in the Inter font semi-bold.

Fixes #20
2022-12-05 20:03:25 -08:00
Will NorrisandWill Norris bb3e973b80 remove static/opensearch.xml
This was replaced by tmpl/opensearch.xml and isn't needed.
2022-12-05 16:53:34 -08:00
Will NorrisandWill Norris f2105a032b README: add docker instructions for volume mount permissions 2022-12-05 12:34:19 -08:00
Will NorrisandWill Norris 4902f25d9f readme: add install and production notes 2022-11-09 17:38:47 -08:00
Will NorrisandWill Norris d346d3c966 all: remove some dead code
go/.export doesn't include click data anymore since we switched over to
sqlite.  Remove that code as well as the Link.Clicks field.  Remove old
/_/export redirect, since we've long since moved off of using it.
2022-11-09 16:53:17 -08:00
Will NorrisandWill Norris 555d1339a8 golink: truncate clicks slice after sorting
previously, the 200 links included in the "popular links" list were
non-deterministic (though those 200 were sorted). Now, always shows the
top 200.
2022-11-09 13:18:01 -08:00
Will Norris 8e1aaaf768 readme: add simple description and screenshot 2022-11-09 08:50:32 -08:00
Will Norris 28cda737e9 .github: add workflow for basic unit tests 2022-11-08 17:25:12 -08:00
Will Norris 72df3a4fad .github: add workflow to build docker image 2022-11-08 16:22:59 -08:00
Will Norris 89c71fd520 bump tailwind and dependencies 2022-11-08 15:04:21 -08:00
Will Norris 86c4be3d46 go.mod: bump to recent snapshot of tailscale.com 2022-11-08 14:20:24 -08:00
Will Norris 1c076779d3 go.mod: align dependencies with tailscale/tailscale 2022-11-08 13:01:07 -08:00
Will Norris 8904b662cc add: add license and headers 2022-11-08 12:53:39 -08:00
Will Norris ae20fe110a all: add flag for specifying snapshot file
We still support directly setting LastSnapshot to support embedding the
snapshot in the binary (like we do internally).  But this allows an
alternate way have restoring backups which doesn't require recompiling
binaries.
2022-11-08 12:32:58 -08:00
Will Norris f3c448c4dd go.mod: bump dependencies 2022-11-08 12:28:39 -08:00
Will Norris 7c148f41c8 all: add standard Dockerfile
Even though we have our own build and deploy scripts, most users will be
more comfortable with a standard Dockerfile.  We could publish our
scripts later if warranted.  For now, we'll just keep them in corp.
2022-11-08 12:00:05 -08:00
Will NorrisandWill Norris 113923a9af all: librarify golink and make importable
Export LastSnapshot var so that snapshots can be stored in separate repo
from the golink code.
2022-08-20 07:25:26 -07:00
Will Norris d4f6b5f22e go.mod: setup new module 2022-08-19 12:10:32 -05:00
Will Norris 18e88921b5 cmd/golink: assume tailnet users exist in devmode
this prevents an error when viewing link detail pages in dev mode.

Change-Id: If62b65599f592215e044767f982a5187887cc1d2
2022-07-02 21:38:07 -07:00
Will Norris 8a19d103dc cmd/golink: add info icon for link details
Change-Id: Ic13864fd1bde11263cc1783accdb6a5678f77253
2022-06-30 08:59:56 -07:00
Will Norris 7c31765ba4 cmd/golink: remove FileDB and associated code
remove FileDB implementation, related flags, and filedb to sqlite
migration code.  Also remove the DB interface since it's no longer
needed.  dev mode now creates a temporary SQLite database.

Change-Id: I22f92dccdd575f6c35a10523ede8ecf85ae330bb
2022-06-29 14:45:51 -07:00
Will Norris ed638ef9d3 cmd/go: add /.detail page for viewing and editing links
This also adds the ability to transfer links to new owners.

Change-Id: I2172291521db82982b0f30b0f9af92a063dc5100
2022-06-29 14:19:05 -07:00
Will Norris a6f3c8ed8d cmd/golink: use relative links
use relative links throughout rather than hardcoding the go hostname,
which allows things to continue working when other hostnames are used.

Change-Id: I5df0d10214799de9722871cbad99bf9af129941f
2022-06-29 13:32:58 -07:00
Will Norris c7f68940d6 cmd/golink: use html/template when rendering pages
Properly use html/template rather than text/template so that we don't
have to worry about escaping data that is passed in to the templates.

Also move the success page into a template for both better rendering and
consistency.

Finally, this includes some tailwind changes that apparently got missed
in previous commits.

Change-Id: Ic658ab940888c44483501e33699da9021be18ecf
2022-06-28 15:35:25 -07:00
Will Norris 2a38b842f7 cmd/golink: enable sqlite and data migration
Add flags to specify sqlite database and migration from files to sqlite.
Migration is only supported in one direction (and flag name makes that
clear). If both sqlite and linkdir flags are provided, sqlite is
preferred.  This has no change in behavior if neither of the new flags
are provided.

Change-Id: Ie13116ec3b80835b4389d228583e7a1476c00bfb
2022-06-16 09:20:09 -07:00
Will Norris 619ecd14bf cmd/golink: add tests for DB implementations
Change-Id: I520aa5053199ff0be56669832aff2603a56f9e6c
2022-06-14 16:02:26 -07:00
Will Norris 4dff66c71c cmd/golink: add SQLiteDB implementation
Change-Id: I70d837e5c1bc65a7a3c13c7e0843f3c361af18ed
2022-06-14 13:00:04 -07:00
Will Norris abf84df32e cmd/golink: provide user documentation
Add a new /.help URL which contains a first pass at user docs, covering
naming rules for short links, using go templates, and basic API access.
Also add client side validation for short name and a link to help page.

Change-Id: I4b66793248eba17e567c4f422ee197617f74ee24
2022-06-21 09:25:14 -07:00
Will Norris ed35fa8624 cmd/golink: autofocus destination input if short exists
When a user visits a non-existing go link, it's reasonable to assume
that they may then want to create that link, so autofocus on the
destination input.

We could also autofocus the short input on initial page load without a
provided short name, but I think that's less of a safe assumption.

Change-Id: Id8e15e2f02f81d319eb782576e5e19f73c0ccee4
2022-06-16 17:06:16 -07:00
Will Norris 67b1a11f57 cmd/golink: display shortname as input group
Change-Id: Ie2d609d495e42b37b9d92d71604646134a512a7b
2022-06-17 17:05:26 -07:00
Will Norris 0a93d9a715 cmd/golink: short names must begin with word char
also move special "system" URLs like /_/export and /_/base to /.export
and /.base, respectively.

Change-Id: Ica2b11ce3f97575c2755ae1516dd4bc6d814ece4
2022-06-14 16:22:07 -07:00
Will Norris 0e1d350bb9 cmd/golink: add stat loading and saving to DB
add new DB.LoadStats and DB.SaveStats methods.  DB.SaveSaveStats takes
an incremental count of clicks since the last call.  This is a noop for
FileDB (the full count is still saved in the Link struct on disk), but
will allow for the SqliteDB to store stats in a separate table with
timestamps to display only recent clicks.

Change-Id: I18c7db871854923b873ae100c844940242a32bb3
2022-06-13 17:40:48 -07:00
Will Norris 4d9c7aa5cd cmd/golink: allow taking over ownerless links
If the previous owner of a link no longer appears in the tailnet users,
any user can overwrite the link and will become the new owner.

Change-Id: I52bbc5e906ff5b1b6424c0e320fd0d02c006ac12
2022-06-10 16:22:50 -07:00
Will Norris 811dd5ae87 cmd/golink: persist click stats for links
store click stats in db.  Hold stats in memory and flush to db every
minute, as well as whenever the /_/export endpoint is called.

Change DB.List() to DB.LoadAll(), since it practice we actually want
the data, not just the names.

Change-Id: I21a3aa19bfc065d595822f004a14b96bbb347de8
2022-06-10 13:21:39 -07:00
Will Norris 3b87ecf59d cmd/golink: support returning json response on save
after successfully saving a golink, return an HTML response only if the
request indicates it can accept text/html, otherwise return JSON.  This
allows for a very simple API:

  % curl -d short=foo -d long=http://foo.com/ go
  {"Short":"foo","Long":"http://foo.com/" ... }

Change-Id: I32e9c028207c5c7b8741d7dd31ebed35cf38a1de
2022-06-10 16:53:51 -07:00
Will Norris 243f7ad377 cmd/golink: print link info when "+" suffix present
append "+" to the end of a golink to get information about the link
rather than being redirected.  For now, this just pretty prints the raw
JSON.  We could make it prettier later.

Change-Id: If25c9f61c326f6e12cdec89b78eb3ca1b741a0ef
2022-06-10 13:53:36 -07:00
Will Norris 41c8dbe5b1 cmd/golink: refactor storage logic into db.go
This is a straight refactor with no functional changes. All file access
is captured in the FileDB type. The DB interface is not strictly
necessary here since we only have a single implementation, but helped to
keep the API clean, which will be useful in a future sqlite migration.

Change-Id: I9b86db3040e2618a4ffef237369288ccfc10bc1e
2022-06-10 10:11:11 -07:00
Will Norris 7f69882100 cmd/golink: fix scaling on mobile
apparently also pickup some stray tailwind changes

Change-Id: I8bf5ba4b4f6d185edf45f6c85f9d7cae3637de76
2022-06-09 09:46:37 -07:00
Will Norris 5f349bb6d2 cmd/golink: add styling using tailwind
Change-Id: I301e1d6a9b38de3762c1e9e92c1fff6ccd873afd
2022-06-08 09:16:45 -07:00
Will Norris 259ce77cdc cmd/golink: move home template into separate file
This sets up an embed.FS even though we only have the one file right
now, as we will have more shortly.

Change-Id: I1292e4c00602fbfc3a7bc2a5f93a8c9b9e6715c0
2022-06-07 13:49:29 -07:00
Will Norris 47351686f5 cmd/golink: expose PathEscape and QueryEscape funcs
Change-Id: I045d414fdbe265076a76ef6f652196761df3bb2c
2022-06-06 15:45:16 -07:00
Will Norris 4f58c2b81c cmd/golink: add support for templates in long URLs
long URLs are now executed using text/template to allow for more advaned
handling.  Templates have access to PathEscape and QueryEscape funcs, as
well as a data struct containing the current time (Now) and the
remaining path from the user-provided short link (Path).

Change-Id: Iedbbafccf98c4a623d06e9519877c7137ca559e8
2022-06-03 16:47:00 -07:00
Will Norris 28227f8267 golink: add validation of short names
Change-Id: Ic288d699e50dcd5367ee163225be37f044e7ef12
2022-06-03 11:09:19 -07:00
Will Norris 7460caa6de golink: ignore hyphens and allow changing name
- ignore hyphens, preventing link ambiguity. If hyphens are included
  when creating the link, they are saved as the "canonical" name for
  the link, but links are still resolved without them.

- allow overwriting the "canonical" name for a short link by simply
  recreating it with the new canonical name. Stats are not updated when
  the canonical name is updated, which is probably fine.

Change-Id: Ia962caa846489850784ef15cdfad7f13bafd8842
2022-06-03 10:56:01 -07:00