github.com/hairyhenderson/gomplate/v4@v4.0.0-pre-2.0.20240520121557-362f058f0c93/internal/datafs/vaultauth.go (about) 1 package datafs 2 3 import ( 4 "context" 5 "fmt" 6 "io/fs" 7 "os" 8 9 "github.com/hairyhenderson/go-fsimpl/vaultfs/vaultauth" 10 "github.com/hairyhenderson/gomplate/v4/internal/deprecated" 11 "github.com/hairyhenderson/gomplate/v4/internal/iohelpers" 12 "github.com/hashicorp/vault/api" 13 "github.com/hashicorp/vault/api/auth/aws" 14 ) 15 16 // compositeVaultAuthMethod configures the auth method based on environment 17 // variables. It extends [vaultfs.EnvAuthMethod] by falling back to AWS EC2 18 // authentication if the other methods fail. 19 func compositeVaultAuthMethod(envFsys fs.FS) api.AuthMethod { 20 return vaultauth.CompositeAuthMethod( 21 vaultauth.EnvAuthMethod(), 22 envEC2AuthAdapter(envFsys), 23 ) 24 } 25 26 // func CompositeVaultAuthMethod() api.AuthMethod { 27 // return compositeVaultAuthMethod(WrapWdFS(osfs.NewFS())) 28 // } 29 30 // envEC2AuthAdapter builds an AWS EC2 authentication method from environment 31 // variables, for use only with [CompositeVaultAuthMethod] 32 func envEC2AuthAdapter(envFS fs.FS) api.AuthMethod { 33 mountPath := GetenvFsys(envFS, "VAULT_AUTH_AWS_MOUNT", "aws") 34 35 nonce := GetenvFsys(envFS, "VAULT_AUTH_AWS_NONCE") 36 role := GetenvFsys(envFS, "VAULT_AUTH_AWS_ROLE") 37 38 // temporary workaround while we wait to deprecate AWS_META_ENDPOINT 39 if endpoint := os.Getenv("AWS_META_ENDPOINT"); endpoint != "" { 40 deprecated.WarnDeprecated(context.Background(), "Use AWS_EC2_METADATA_SERVICE_ENDPOINT instead of AWS_META_ENDPOINT") 41 if os.Getenv("AWS_EC2_METADATA_SERVICE_ENDPOINT") == "" { 42 os.Setenv("AWS_EC2_METADATA_SERVICE_ENDPOINT", endpoint) 43 } 44 } 45 46 awsauth, err := aws.NewAWSAuth( 47 aws.WithEC2Auth(), 48 aws.WithMountPath(mountPath), 49 aws.WithNonce(nonce), 50 aws.WithRole(role), 51 ) 52 if err != nil { 53 return nil 54 } 55 56 output := GetenvFsys(envFS, "VAULT_AUTH_AWS_NONCE_OUTPUT") 57 if output == "" { 58 return awsauth 59 } 60 61 return &ec2AuthNonceWriter{AWSAuth: awsauth, nonce: nonce, output: output} 62 } 63 64 // ec2AuthNonceWriter - wraps an AWSAuth, and writes the nonce to the nonce 65 // output file 66 type ec2AuthNonceWriter struct { 67 *aws.AWSAuth 68 nonce string 69 output string 70 } 71 72 func (a *ec2AuthNonceWriter) Login(ctx context.Context, client *api.Client) (*api.Secret, error) { 73 secret, err := a.AWSAuth.Login(ctx, client) 74 if err != nil { 75 return nil, err 76 } 77 78 nonce := a.nonce 79 if val, ok := secret.Auth.Metadata["nonce"]; ok { 80 nonce = val 81 } 82 83 err = os.WriteFile(a.output, []byte(nonce+"\n"), iohelpers.NormalizeFileMode(0o600)) 84 if err != nil { 85 return nil, fmt.Errorf("error writing nonce output file: %w", err) 86 } 87 88 return secret, nil 89 }