Skip to content

Commit 622ddf5

Browse files
committed
chore: initial import
0 parents  commit 622ddf5

File tree

11 files changed

+1047
-0
lines changed

11 files changed

+1047
-0
lines changed

.github/workflows/build.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: build
2+
3+
on:
4+
push:
5+
branches:
6+
- '*'
7+
pull_request:
8+
branches:
9+
- main
10+
11+
jobs:
12+
build:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v3
17+
- name: Set up Go
18+
uses: actions/setup-go@v3
19+
with:
20+
go-version: 1.19
21+
- name: Build
22+
run: |
23+
go test ./...
24+
go build cmd/tskeyservice/main.go

.github/workflows/nightly.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: nightly
2+
3+
on: workflow_dispatch
4+
5+
permissions:
6+
contents: write
7+
packages: write
8+
id-token: write
9+
10+
jobs:
11+
release:
12+
runs-on: ubuntu-latest
13+
env:
14+
DOCKER_CLI_EXPERIMENTAL: "enabled"
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v3
18+
with:
19+
fetch-depth: 0
20+
- name: Set up QEMU
21+
uses: docker/setup-qemu-action@v1
22+
- name: Docker Login
23+
uses: docker/login-action@v1
24+
with:
25+
registry: ghcr.io
26+
username: ${{ github.repository_owner }}
27+
password: ${{ secrets.GITHUB_TOKEN }}
28+
- name: Set up Go
29+
uses: actions/setup-go@v3
30+
with:
31+
go-version: 1.19
32+
- name: Install cosign
33+
uses: sigstore/cosign-installer@v2.8.1
34+
- name: Run GoReleaser
35+
uses: goreleaser/goreleaser-action@v2
36+
with:
37+
distribution: goreleaser-pro
38+
version: latest
39+
args: release --nightly --rm-dist
40+
env:
41+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42+
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

.github/workflows/release.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: release
2+
3+
on:
4+
push:
5+
tags:
6+
- '*'
7+
8+
permissions:
9+
contents: write
10+
packages: write
11+
id-token: write
12+
13+
jobs:
14+
release:
15+
runs-on: ubuntu-latest
16+
env:
17+
DOCKER_CLI_EXPERIMENTAL: "enabled"
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v3
21+
with:
22+
fetch-depth: 0
23+
- name: Set up QEMU
24+
uses: docker/setup-qemu-action@v1
25+
- name: Docker Login
26+
uses: docker/login-action@v1
27+
with:
28+
registry: ghcr.io
29+
username: ${{ github.repository_owner }}
30+
password: ${{ secrets.GITHUB_TOKEN }}
31+
- name: Set up Go
32+
uses: actions/setup-go@v3
33+
with:
34+
go-version: 1.19
35+
- name: Install cosign
36+
uses: sigstore/cosign-installer@v2.8.1
37+
- name: Run GoReleaser
38+
uses: goreleaser/goreleaser-action@v2
39+
with:
40+
distribution: goreleaser-pro
41+
version: latest
42+
args: release --rm-dist
43+
env:
44+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45+
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.idea
2+
dist

.goreleaser.yaml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
project_name: tskeyservice
2+
3+
nightly:
4+
name_template: '{{ incminor .Version }}-dev'
5+
6+
before:
7+
hooks:
8+
- go mod tidy
9+
10+
builds:
11+
- main: ./cmd/tskeyservice
12+
env: [ CGO_ENABLED=0 ]
13+
goos:
14+
- linux
15+
- windows
16+
- darwin
17+
goarch:
18+
- amd64
19+
- arm64
20+
ignore:
21+
- goos: windows
22+
goarch: arm64
23+
ldflags:
24+
- -s -w
25+
26+
checksum:
27+
name_template: "checksums.txt"
28+
29+
dockers:
30+
- image_templates: [ "ghcr.io/jsiebens/{{ .ProjectName }}:{{ .Version }}-amd64" ]
31+
dockerfile: Dockerfile
32+
use: buildx
33+
build_flag_templates:
34+
- --platform=linux/amd64
35+
- image_templates: [ "ghcr.io/jsiebens/{{ .ProjectName }}:{{ .Version }}-arm64" ]
36+
goarch: arm64
37+
dockerfile: Dockerfile
38+
use: buildx
39+
build_flag_templates:
40+
- --platform=linux/arm64
41+
42+
docker_manifests:
43+
- name_template: ghcr.io/jsiebens/{{ .ProjectName }}:{{ .Version }}
44+
image_templates:
45+
- ghcr.io/jsiebens/{{ .ProjectName }}:{{ .Version }}-amd64
46+
- ghcr.io/jsiebens/{{ .ProjectName }}:{{ .Version }}-arm64
47+
- name_template: ghcr.io/jsiebens/{{ .ProjectName }}:{{ if .IsNightly }}dev{{ else }}latest{{ end }}
48+
image_templates:
49+
- ghcr.io/jsiebens/{{ .ProjectName }}:{{ .Version }}-amd64
50+
- ghcr.io/jsiebens/{{ .ProjectName }}:{{ .Version }}-arm64
51+
52+
signs:
53+
- cmd: cosign
54+
env:
55+
- COSIGN_EXPERIMENTAL=1
56+
certificate: '${artifact}.pem'
57+
args:
58+
- sign-blob
59+
- '--output-certificate=${certificate}'
60+
- '--output-signature=${signature}'
61+
- '${artifact}'
62+
artifacts: checksum
63+
64+
docker_signs:
65+
- cmd: cosign
66+
env:
67+
- COSIGN_EXPERIMENTAL=1
68+
artifacts: all
69+
output: true
70+
args:
71+
- sign
72+
- '${artifact}'
73+
74+
archives:
75+
- format: binary
76+
name_template: '{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}'
77+
78+
release:
79+
prerelease: auto
80+
81+
changelog:
82+
sort: asc
83+
filters:
84+
exclude:
85+
- '^test:'
86+
- '^chore'
87+
- '^docs'
88+
- Merge pull request
89+
- Merge remote-tracking branch
90+
- Merge branch
91+
- go mod tidy
92+
groups:
93+
- title: 'New Features'
94+
regexp: "^.*feat[(\\w)]*:+.*$"
95+
order: 0
96+
- title: 'Bug fixes'
97+
regexp: "^.*fix[(\\w)]*:+.*$"
98+
order: 10
99+
- title: Other work
100+
order: 999

Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM --platform=${BUILDPLATFORM:-linux/amd64} alpine:3.16.2
2+
3+
COPY tskeyservice /usr/local/bin/tskeyservice
4+
5+
RUN mkdir -p /data/tskeyservice
6+
WORKDIR /data/tskeyservice
7+
8+
ENTRYPOINT ["/usr/local/bin/tskeyservice"]

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Johan Siebens
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Whitespace-only changes.

cmd/tskeyservice/main.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"github.com/coreos/go-oidc/v3/oidc"
6+
"github.com/hashicorp/go-bexpr"
7+
"github.com/labstack/echo/v4"
8+
"github.com/tailscale/tailscale-client-go/tailscale"
9+
"log"
10+
"net/http"
11+
"os"
12+
"strings"
13+
)
14+
15+
const BEARER_SCHEMA = "Bearer "
16+
17+
type KeyResponse struct {
18+
Key string `json:"key"`
19+
}
20+
21+
func start() error {
22+
ctx := context.Background()
23+
24+
apiKey := os.Getenv("TS_API_KEY")
25+
tailnet := os.Getenv("TS_TAILNET")
26+
issuer := os.Getenv("TS_KEYS_ISSUER")
27+
tags := os.Getenv("TS_KEYS_TAGS")
28+
filter := os.Getenv("TS_KEYS_BEXPR")
29+
30+
client, err := tailscale.NewClient(apiKey, tailnet)
31+
if err != nil {
32+
return err
33+
}
34+
35+
provider, err := oidc.NewProvider(ctx, issuer)
36+
if err != nil {
37+
return err
38+
}
39+
40+
verifier := provider.Verifier(&oidc.Config{SkipClientIDCheck: true})
41+
42+
evaluator, err := bexpr.CreateEvaluator(filter)
43+
if err != nil {
44+
return err
45+
}
46+
47+
expirySeconds := uint64(300)
48+
capabilities := tailscale.KeyCapabilities{}
49+
capabilities.Devices.Create.Reusable = false
50+
capabilities.Devices.Create.Ephemeral = true
51+
if len(tags) != 0 {
52+
capabilities.Devices.Create.Tags = strings.Split(tags, ",")
53+
}
54+
55+
e := echo.New()
56+
e.HideBanner = true
57+
e.GET("/key", func(c echo.Context) error {
58+
ctx := c.Request().Context()
59+
60+
authHeader := c.Request().Header.Get("Authorization")
61+
62+
if len(authHeader) == 0 || !strings.HasPrefix(authHeader, BEARER_SCHEMA) {
63+
return echo.ErrUnauthorized
64+
}
65+
66+
idToken, err := verifier.Verify(ctx, authHeader[len(BEARER_SCHEMA):])
67+
if err != nil {
68+
return echo.ErrBadRequest
69+
}
70+
71+
var claims = make(map[string]interface{})
72+
if err := idToken.Claims(&claims); err != nil {
73+
return echo.ErrBadRequest
74+
}
75+
76+
if ok, _ := evaluator.Evaluate(claims); ok {
77+
key, err := client.CreateKey(ctx, capabilities, tailscale.WithKeyExpirySeconds(expirySeconds))
78+
if err != nil {
79+
return echo.ErrInternalServerError
80+
}
81+
82+
return c.JSON(http.StatusOK, &KeyResponse{Key: key.Key})
83+
}
84+
85+
return echo.ErrForbidden
86+
})
87+
88+
return e.Start(":8080")
89+
}
90+
91+
func main() {
92+
if err := start(); err != nil {
93+
log.Fatal(err)
94+
}
95+
}

go.mod

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module github.com/jsiebens/tskeyservice
2+
3+
go 1.19
4+
5+
replace github.com/tailscale/tailscale-client-go v1.7.0 => github.com/jsiebens/tailscale-client-go v0.0.0-20221108073316-a64d102ba541
6+
7+
require (
8+
github.com/coreos/go-oidc/v3 v3.4.0
9+
github.com/hashicorp/go-bexpr v0.1.11
10+
github.com/labstack/echo/v4 v4.9.1
11+
github.com/tailscale/tailscale-client-go v1.7.0
12+
)
13+
14+
require (
15+
github.com/golang/protobuf v1.5.2 // indirect
16+
github.com/labstack/gommon v0.4.0 // indirect
17+
github.com/mattn/go-colorable v0.1.11 // indirect
18+
github.com/mattn/go-isatty v0.0.14 // indirect
19+
github.com/mitchellh/mapstructure v1.4.1 // indirect
20+
github.com/mitchellh/pointerstructure v1.2.1 // indirect
21+
github.com/tailscale/hujson v0.0.0-20220506213045-af5ed07155e5 // indirect
22+
github.com/valyala/bytebufferpool v1.0.0 // indirect
23+
github.com/valyala/fasttemplate v1.2.1 // indirect
24+
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
25+
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect
26+
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 // indirect
27+
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
28+
golang.org/x/text v0.3.7 // indirect
29+
google.golang.org/appengine v1.6.7 // indirect
30+
google.golang.org/protobuf v1.28.0 // indirect
31+
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
32+
)

0 commit comments

Comments
 (0)