configurationprovider.go raw
1 package oraclecloud
2
3 import (
4 "crypto/rsa"
5 "encoding/base64"
6 "errors"
7 "fmt"
8 "os"
9 "slices"
10 "strings"
11
12 "github.com/go-acme/lego/v4/log"
13 "github.com/go-acme/lego/v4/platform/config/env"
14 "github.com/nrdcg/oci-go-sdk/common/v1065"
15 )
16
17 type environmentConfigurationProvider struct {
18 values map[string]string
19 }
20
21 func newEnvironmentConfigurationProvider() (*environmentConfigurationProvider, error) {
22 values, err := env.GetWithFallback(
23 []string{EnvRegion, altEnvTFVarRegion},
24 []string{EnvUserOCID, altEnvTFVarUserOCID},
25 []string{EnvTenancyOCID, altEnvTFVarTenancyOCID},
26 []string{EnvPubKeyFingerprint, altEnvFingerprint, altEnvTFVarFingerprint},
27 )
28 if err != nil {
29 return nil, err
30 }
31
32 return &environmentConfigurationProvider{
33 values: values,
34 }, nil
35 }
36
37 func (p *environmentConfigurationProvider) PrivateRSAKey() (*rsa.PrivateKey, error) {
38 privateKey, err := getPrivateKey()
39 if err != nil {
40 return nil, err
41 }
42
43 return common.PrivateKeyFromBytesWithPassword(privateKey, []byte(p.privateKeyPassword()))
44 }
45
46 func (p *environmentConfigurationProvider) KeyID() (string, error) {
47 tenancy, err := p.TenancyOCID()
48 if err != nil {
49 return "", err
50 }
51
52 user, err := p.UserOCID()
53 if err != nil {
54 return "", err
55 }
56
57 fingerprint, err := p.KeyFingerprint()
58 if err != nil {
59 return "", err
60 }
61
62 return fmt.Sprintf("%s/%s/%s", tenancy, user, fingerprint), nil
63 }
64
65 func (p *environmentConfigurationProvider) TenancyOCID() (string, error) {
66 return p.values[EnvTenancyOCID], nil
67 }
68
69 func (p *environmentConfigurationProvider) UserOCID() (string, error) {
70 return p.values[EnvUserOCID], nil
71 }
72
73 func (p *environmentConfigurationProvider) KeyFingerprint() (string, error) {
74 return p.values[EnvPubKeyFingerprint], nil
75 }
76
77 func (p *environmentConfigurationProvider) Region() (string, error) {
78 return p.values[EnvRegion], nil
79 }
80
81 func (p *environmentConfigurationProvider) AuthType() (common.AuthConfig, error) {
82 // Inspired by https://github.com/oracle/oci-go-sdk/blob/e7635c292e60d0a9dcdd3a1e7de180d7c99b1eee/common/configuration.go#L231-L234
83 return common.AuthConfig{AuthType: common.UnknownAuthenticationType}, errors.New("unsupported, keep the interface")
84 }
85
86 func (p *environmentConfigurationProvider) privateKeyPassword() string {
87 return env.GetOneWithFallback(EnvPrivKeyPass, "", env.ParseString, altEnvPrivateKeyPassword, altEnvTFVarPrivateKeyPassword)
88 }
89
90 func getPrivateKey() ([]byte, error) {
91 base64EnvKeys := []string{envPrivKey, altEnvPrivateKey}
92
93 envVarValue := getEnvWithStrictFallback(base64EnvKeys...)
94 if envVarValue != "" {
95 bytes, err := base64.StdEncoding.DecodeString(envVarValue)
96 if err != nil {
97 return nil, fmt.Errorf("failed to read base64 value %s (defined by env vars %s): %w", envVarValue,
98 strings.Join(base64EnvKeys, " or "), err)
99 }
100
101 return bytes, nil
102 }
103
104 fileEnvKeys := []string{EnvPrivKeyFile, altEnvPrivateKeyPath, altEnvTFVarPrivateKeyPath}
105
106 fileVarValue := getEnvFileWithStrictFallback(fileEnvKeys...)
107 if len(fileVarValue) == 0 {
108 return nil, fmt.Errorf("no value provided for: %s",
109 strings.Join(slices.Concat(base64EnvKeys, fileEnvKeys), " or "),
110 )
111 }
112
113 return fileVarValue, nil
114 }
115
116 func getEnvWithStrictFallback(keys ...string) string {
117 for _, key := range keys {
118 envVarValue := os.Getenv(key)
119 if envVarValue != "" {
120 return envVarValue
121 }
122 }
123
124 return ""
125 }
126
127 func getEnvFileWithStrictFallback(keys ...string) []byte {
128 for _, key := range keys {
129 fileVarValue := os.Getenv(key)
130 if fileVarValue == "" {
131 continue
132 }
133
134 fileContents, err := os.ReadFile(fileVarValue)
135 if err != nil {
136 log.Printf("Failed to read the file %s (defined by env var %s): %s", fileVarValue, key, err)
137 return nil
138 }
139
140 return fileContents
141 }
142
143 return nil
144 }
145