cmd/tailscale/cli: allow fetching keys from AWS Parameter Store
This allows fetching auth keys, OAuth client secrets, and ID tokens (for
workload identity federation) from AWS Parameter Store by passing an ARN
as the value. This is a relatively low-overhead mechanism for fetching
these values from an external secret store without needing to run a
secret service.
Usage examples:
# Auth key
tailscale up \
--auth-key=arn:aws:ssm:us-east-1:123456789012:parameter/tailscale/auth-key
# OAuth client secret
tailscale up \
--client-secret=arn:aws:ssm:us-east-1:123456789012:parameter/tailscale/oauth-secret \
--advertise-tags=tag:server
# ID token (for workload identity federation)
tailscale up \
--client-id=my-client \
--id-token=arn:aws:ssm:us-east-1:123456789012:parameter/tailscale/id-token \
--advertise-tags=tag:server
Updates tailscale/corp#28792
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
This commit is contained in:
committed by
Andrew Dunham
parent
65d6793204
commit
bcceef3682
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !ts_omit_aws
|
||||
|
||||
package awsparamstore
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseARN(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
wantOk bool
|
||||
wantRegion string
|
||||
wantParamName string
|
||||
}{
|
||||
{
|
||||
name: "non-arn-passthrough",
|
||||
input: "tskey-abcd1234",
|
||||
wantOk: false,
|
||||
},
|
||||
{
|
||||
name: "file-prefix-passthrough",
|
||||
input: "file:/path/to/key",
|
||||
wantOk: false,
|
||||
},
|
||||
{
|
||||
name: "empty-passthrough",
|
||||
input: "",
|
||||
wantOk: false,
|
||||
},
|
||||
{
|
||||
name: "non-ssm-arn-passthrough",
|
||||
input: "arn:aws:s3:::my-bucket",
|
||||
wantOk: false,
|
||||
},
|
||||
{
|
||||
name: "invalid-arn-passthrough",
|
||||
input: "arn:invalid",
|
||||
wantOk: false,
|
||||
},
|
||||
{
|
||||
name: "arn-invalid-resource-passthrough",
|
||||
input: "arn:aws:ssm:us-east-1:123456789012:document/myDoc",
|
||||
wantOk: false,
|
||||
},
|
||||
{
|
||||
name: "valid-arn",
|
||||
input: "arn:aws:ssm:us-west-2:123456789012:parameter/my-secret",
|
||||
wantOk: true,
|
||||
wantRegion: "us-west-2",
|
||||
wantParamName: "/my-secret",
|
||||
},
|
||||
{
|
||||
name: "valid-arn-with-path",
|
||||
input: "arn:aws:ssm:eu-central-1:123456789012:parameter/path/to/secret",
|
||||
wantOk: true,
|
||||
wantRegion: "eu-central-1",
|
||||
wantParamName: "/path/to/secret",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotRegion, gotParamName, gotOk := parseARN(tt.input)
|
||||
if gotOk != tt.wantOk {
|
||||
t.Errorf("parseARN(%q) got ok=%v, want %v", tt.input, gotOk, tt.wantOk)
|
||||
}
|
||||
if !tt.wantOk {
|
||||
return
|
||||
}
|
||||
if gotRegion != tt.wantRegion {
|
||||
t.Errorf("parseARN(%q) got region=%q, want %q", tt.input, gotRegion, tt.wantRegion)
|
||||
}
|
||||
if gotParamName != tt.wantParamName {
|
||||
t.Errorf("parseARN(%q) got paramName=%q, want %q", tt.input, gotParamName, tt.wantParamName)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user