Something went wrong. Try again.
forked from tailscale/tailscale
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889// Copyright (c) Tailscale Inc & contributors// SPDX-License-Identifier: BSD-3-Clause
//go:build !ts_omit_aws
// Package awsparamstore registers support for fetching secret values from AWS// Parameter Store.package awsparamstore
import ( "context" "fmt" "strings"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws/arn" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/ssm" "tailscale.com/feature" "tailscale.com/internal/client/tailscale")
func init() { feature.Register("awsparamstore") tailscale.HookResolveValueFromParameterStore.Set(ResolveValue)}
// parseARN parses and verifies that the input string is an// ARN for AWS Parameter Store, returning the region and parameter name if so.//// If the input is not a valid Parameter Store ARN, it returns ok==false.func parseARN(s string) (region, parameterName string, ok bool) { parsed, err := arn.Parse(s) if err != nil { return "", "", false }
if parsed.Service != "ssm" { return "", "", false } parameterName, ok = strings.CutPrefix(parsed.Resource, "parameter/") if !ok { return "", "", false }
// NOTE: parameter names must have a leading slash return parsed.Region, "/" + parameterName, true}
// ResolveValue fetches a value from AWS Parameter Store if the input// looks like an SSM ARN (e.g., arn:aws:ssm:us-east-1:123456789012:parameter/my-secret).//// If the input is not a Parameter Store ARN, it returns the value unchanged.//// If the input is a Parameter Store ARN and fetching the parameter fails, it// returns an error.func ResolveValue(ctx context.Context, valueOrARN string) (string, error) { // If it doesn't look like an ARN, return as-is region, parameterName, ok := parseARN(valueOrARN) if !ok { return valueOrARN, nil }
// Load AWS config with the region from the ARN cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(region)) if err != nil { return "", fmt.Errorf("loading AWS config in region %q: %w", region, err) }
// Create SSM client and fetch the parameter client := ssm.NewFromConfig(cfg) output, err := client.GetParameter(ctx, &ssm.GetParameterInput{ // The parameter to fetch. Name: aws.String(parameterName),
// If the parameter is a SecureString, decrypt it. WithDecryption: aws.Bool(true), }) if err != nil { return "", fmt.Errorf("getting SSM parameter %q: %w", parameterName, err) }
if output.Parameter == nil || output.Parameter.Value == nil { return "", fmt.Errorf("SSM parameter %q has no value", parameterName) }
return strings.TrimSpace(*output.Parameter.Value), nil}