1//go:build example && go18
2// +build example,go18
3
4package main
5
6import (
7	"encoding/json"
8	"os"
9
10	"github.com/pkg/errors"
11)
12
13// Example plugin that will retrieve credentials from a JSON file that the
14// "PLUGIN_CREDS_FILE" environment variable points to
15//
16// Build with:
17//   go build -tags example -o plugin.so -buildmode=plugin plugin.go
18func main() {}
19
20var myCredProvider provider
21
22func init() {
23	// Initialize a mock credential provider with stubs
24	myCredProvider = provider{Filename: os.Getenv("PLUGIN_CREDS_FILE")}
25}
26
27// GetAWSSDKCredentialProvider is the symbol SDK will lookup and use to
28// get the credential provider's retrieve and isExpired functions.
29func GetAWSSDKCredentialProvider() (func() (key, secret, token string, err error), func() bool) {
30	return myCredProvider.Retrieve, myCredProvider.IsExpired
31}
32
33// mock implementation of a type that returns retrieves credentials and
34// returns if they have expired.
35type provider struct {
36	Filename string
37
38	loaded bool
39}
40
41func (p *provider) Retrieve() (key, secret, token string, err error) {
42	f, err := os.Open(p.Filename)
43	if err != nil {
44		return "", "", "", errors.Wrapf(err, "failed to open credentials file, %q", p.Filename)
45	}
46	decoder := json.NewDecoder(f)
47
48	creds := struct {
49		Key, Secret, Token string
50	}{}
51
52	if err := decoder.Decode(&creds); err != nil {
53		return "", "", "", errors.Wrap(err, "failed to decode credentials file")
54	}
55
56	p.loaded = true
57	return creds.Key, creds.Secret, creds.Token, nil
58}
59
60func (p *provider) IsExpired() bool {
61	return !p.loaded
62}
63