diff options
Diffstat (limited to 'cmd/gitops-pusher')
| -rw-r--r-- | cmd/gitops-pusher/.gitignore | 2 | ||||
| -rw-r--r-- | cmd/gitops-pusher/README.md | 96 | ||||
| -rw-r--r-- | cmd/gitops-pusher/cache.go | 132 | ||||
| -rw-r--r-- | cmd/gitops-pusher/gitops-pusher_test.go | 110 |
4 files changed, 170 insertions, 170 deletions
diff --git a/cmd/gitops-pusher/.gitignore b/cmd/gitops-pusher/.gitignore index 504452249..eeed6e4bf 100644 --- a/cmd/gitops-pusher/.gitignore +++ b/cmd/gitops-pusher/.gitignore @@ -1 +1 @@ -version-cache.json +version-cache.json
diff --git a/cmd/gitops-pusher/README.md b/cmd/gitops-pusher/README.md index 9f77ea970..b08125397 100644 --- a/cmd/gitops-pusher/README.md +++ b/cmd/gitops-pusher/README.md @@ -1,48 +1,48 @@ -# gitops-pusher - -This is a small tool to help people achieve a -[GitOps](https://about.gitlab.com/topics/gitops/) workflow with Tailscale ACL -changes. This tool is intended to be used in a CI flow that looks like this: - -```yaml -name: Tailscale ACL syncing - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - acls: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup Go environment - uses: actions/setup-go@v3.2.0 - - - name: Install gitops-pusher - run: go install tailscale.com/cmd/gitops-pusher@latest - - - name: Deploy ACL - if: github.event_name == 'push' - env: - TS_API_KEY: ${{ secrets.TS_API_KEY }} - TS_TAILNET: ${{ secrets.TS_TAILNET }} - run: | - ~/go/bin/gitops-pusher --policy-file ./policy.hujson apply - - - name: ACL tests - if: github.event_name == 'pull_request' - env: - TS_API_KEY: ${{ secrets.TS_API_KEY }} - TS_TAILNET: ${{ secrets.TS_TAILNET }} - run: | - ~/go/bin/gitops-pusher --policy-file ./policy.hujson test -``` - -Change the value of the `--policy-file` flag to point to the policy file on -disk. Policy files should be in [HuJSON](https://github.com/tailscale/hujson) -format. +# gitops-pusher
+
+This is a small tool to help people achieve a
+[GitOps](https://about.gitlab.com/topics/gitops/) workflow with Tailscale ACL
+changes. This tool is intended to be used in a CI flow that looks like this:
+
+```yaml
+name: Tailscale ACL syncing
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ acls:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Go environment
+ uses: actions/setup-go@v3.2.0
+
+ - name: Install gitops-pusher
+ run: go install tailscale.com/cmd/gitops-pusher@latest
+
+ - name: Deploy ACL
+ if: github.event_name == 'push'
+ env:
+ TS_API_KEY: ${{ secrets.TS_API_KEY }}
+ TS_TAILNET: ${{ secrets.TS_TAILNET }}
+ run: |
+ ~/go/bin/gitops-pusher --policy-file ./policy.hujson apply
+
+ - name: ACL tests
+ if: github.event_name == 'pull_request'
+ env:
+ TS_API_KEY: ${{ secrets.TS_API_KEY }}
+ TS_TAILNET: ${{ secrets.TS_TAILNET }}
+ run: |
+ ~/go/bin/gitops-pusher --policy-file ./policy.hujson test
+```
+
+Change the value of the `--policy-file` flag to point to the policy file on
+disk. Policy files should be in [HuJSON](https://github.com/tailscale/hujson)
+format.
diff --git a/cmd/gitops-pusher/cache.go b/cmd/gitops-pusher/cache.go index 6792e5e63..89225e6f8 100644 --- a/cmd/gitops-pusher/cache.go +++ b/cmd/gitops-pusher/cache.go @@ -1,66 +1,66 @@ -// Copyright (c) Tailscale Inc & AUTHORS -// SPDX-License-Identifier: BSD-3-Clause - -package main - -import ( - "encoding/json" - "os" -) - -// Cache contains cached information about the last time this tool was run. -// -// This is serialized to a JSON file that should NOT be checked into git. -// It should be managed with either CI cache tools or stored locally somehow. The -// exact mechanism is irrelevant as long as it is consistent. -// -// This allows gitops-pusher to detect external ACL changes. I'm not sure what to -// call this problem, so I've been calling it the "three version problem" in my -// notes. The basic problem is that at any given time we only have two versions -// of the ACL file at any given point. In order to check if there has been -// tampering of the ACL files in the admin panel, we need to have a _third_ version -// to compare against. -// -// In this case I am not storing the old ACL entirely (though that could be a -// reasonable thing to add in the future), but only its sha256sum. This allows -// us to detect if the shasum in control matches the shasum we expect, and if that -// expectation fails, then we can react accordingly. -type Cache struct { - PrevETag string // Stores the previous ETag of the ACL to allow -} - -// Save persists the cache to a given file. -func (c *Cache) Save(fname string) error { - os.Remove(fname) - fout, err := os.Create(fname) - if err != nil { - return err - } - defer fout.Close() - - return json.NewEncoder(fout).Encode(c) -} - -// LoadCache loads the cache from a given file. -func LoadCache(fname string) (*Cache, error) { - var result Cache - - fin, err := os.Open(fname) - if err != nil { - return nil, err - } - defer fin.Close() - - err = json.NewDecoder(fin).Decode(&result) - if err != nil { - return nil, err - } - - return &result, nil -} - -// Shuck removes the first and last character of a string, analogous to -// shucking off the husk of an ear of corn. -func Shuck(s string) string { - return s[1 : len(s)-1] -} +// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+package main
+
+import (
+ "encoding/json"
+ "os"
+)
+
+// Cache contains cached information about the last time this tool was run.
+//
+// This is serialized to a JSON file that should NOT be checked into git.
+// It should be managed with either CI cache tools or stored locally somehow. The
+// exact mechanism is irrelevant as long as it is consistent.
+//
+// This allows gitops-pusher to detect external ACL changes. I'm not sure what to
+// call this problem, so I've been calling it the "three version problem" in my
+// notes. The basic problem is that at any given time we only have two versions
+// of the ACL file at any given point. In order to check if there has been
+// tampering of the ACL files in the admin panel, we need to have a _third_ version
+// to compare against.
+//
+// In this case I am not storing the old ACL entirely (though that could be a
+// reasonable thing to add in the future), but only its sha256sum. This allows
+// us to detect if the shasum in control matches the shasum we expect, and if that
+// expectation fails, then we can react accordingly.
+type Cache struct {
+ PrevETag string // Stores the previous ETag of the ACL to allow
+}
+
+// Save persists the cache to a given file.
+func (c *Cache) Save(fname string) error {
+ os.Remove(fname)
+ fout, err := os.Create(fname)
+ if err != nil {
+ return err
+ }
+ defer fout.Close()
+
+ return json.NewEncoder(fout).Encode(c)
+}
+
+// LoadCache loads the cache from a given file.
+func LoadCache(fname string) (*Cache, error) {
+ var result Cache
+
+ fin, err := os.Open(fname)
+ if err != nil {
+ return nil, err
+ }
+ defer fin.Close()
+
+ err = json.NewDecoder(fin).Decode(&result)
+ if err != nil {
+ return nil, err
+ }
+
+ return &result, nil
+}
+
+// Shuck removes the first and last character of a string, analogous to
+// shucking off the husk of an ear of corn.
+func Shuck(s string) string {
+ return s[1 : len(s)-1]
+}
diff --git a/cmd/gitops-pusher/gitops-pusher_test.go b/cmd/gitops-pusher/gitops-pusher_test.go index b050761d9..1beb049c6 100644 --- a/cmd/gitops-pusher/gitops-pusher_test.go +++ b/cmd/gitops-pusher/gitops-pusher_test.go @@ -1,55 +1,55 @@ -// Copyright (c) Tailscale Inc & AUTHORS -// SPDX-License-Identifier: BSD-3-Clause -package main - -import ( - "encoding/json" - "strings" - "testing" - - "tailscale.com/client/tailscale" -) - -func TestEmbeddedTypeUnmarshal(t *testing.T) { - var gitopsErr ACLGitopsTestError - gitopsErr.Message = "gitops response error" - gitopsErr.Data = []tailscale.ACLTestFailureSummary{ - { - User: "GitopsError", - Errors: []string{"this was initially created as a gitops error"}, - }, - } - - var aclTestErr tailscale.ACLTestError - aclTestErr.Message = "native ACL response error" - aclTestErr.Data = []tailscale.ACLTestFailureSummary{ - { - User: "ACLError", - Errors: []string{"this was initially created as an ACL error"}, - }, - } - - t.Run("unmarshal gitops type from acl type", func(t *testing.T) { - b, _ := json.Marshal(aclTestErr) - var e ACLGitopsTestError - err := json.Unmarshal(b, &e) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(e.Error(), "For user ACLError") { // the gitops error prints out the user, the acl error doesn't - t.Fatalf("user heading for 'ACLError' not found in gitops error: %v", e.Error()) - } - }) - t.Run("unmarshal acl type from gitops type", func(t *testing.T) { - b, _ := json.Marshal(gitopsErr) - var e tailscale.ACLTestError - err := json.Unmarshal(b, &e) - if err != nil { - t.Fatal(err) - } - expectedErr := `Status: 0, Message: "gitops response error", Data: [{User:GitopsError Errors:[this was initially created as a gitops error] Warnings:[]}]` - if e.Error() != expectedErr { - t.Fatalf("got %v\n, expected %v", e.Error(), expectedErr) - } - }) -} +// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+package main
+
+import (
+ "encoding/json"
+ "strings"
+ "testing"
+
+ "tailscale.com/client/tailscale"
+)
+
+func TestEmbeddedTypeUnmarshal(t *testing.T) {
+ var gitopsErr ACLGitopsTestError
+ gitopsErr.Message = "gitops response error"
+ gitopsErr.Data = []tailscale.ACLTestFailureSummary{
+ {
+ User: "GitopsError",
+ Errors: []string{"this was initially created as a gitops error"},
+ },
+ }
+
+ var aclTestErr tailscale.ACLTestError
+ aclTestErr.Message = "native ACL response error"
+ aclTestErr.Data = []tailscale.ACLTestFailureSummary{
+ {
+ User: "ACLError",
+ Errors: []string{"this was initially created as an ACL error"},
+ },
+ }
+
+ t.Run("unmarshal gitops type from acl type", func(t *testing.T) {
+ b, _ := json.Marshal(aclTestErr)
+ var e ACLGitopsTestError
+ err := json.Unmarshal(b, &e)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !strings.Contains(e.Error(), "For user ACLError") { // the gitops error prints out the user, the acl error doesn't
+ t.Fatalf("user heading for 'ACLError' not found in gitops error: %v", e.Error())
+ }
+ })
+ t.Run("unmarshal acl type from gitops type", func(t *testing.T) {
+ b, _ := json.Marshal(gitopsErr)
+ var e tailscale.ACLTestError
+ err := json.Unmarshal(b, &e)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expectedErr := `Status: 0, Message: "gitops response error", Data: [{User:GitopsError Errors:[this was initially created as a gitops error] Warnings:[]}]`
+ if e.Error() != expectedErr {
+ t.Fatalf("got %v\n, expected %v", e.Error(), expectedErr)
+ }
+ })
+}
|
