forked from hashicorp/terraform-provider-vault
/
resource_aws_auth_backend_cert.go
184 lines (156 loc) · 5.55 KB
/
resource_aws_auth_backend_cert.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package vault
import (
"encoding/base64"
"fmt"
"log"
"regexp"
"strings"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/hashicorp/vault/api"
)
var (
awsAuthBackendCertBackendFromPathRegex = regexp.MustCompile("^auth/(.+)/config/certificate/.+$")
awsAuthBackendCertNameFromPathRegex = regexp.MustCompile("^auth/.+/config/certificate/(.+$)")
)
func awsAuthBackendCertResource() *schema.Resource {
return &schema.Resource{
Create: awsAuthBackendCertCreate,
Read: awsAuthBackendCertRead,
Delete: awsAuthBackendCertDelete,
Exists: awsAuthBackendCertExists,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"cert_name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the certificate to configure.",
ForceNew: true,
},
"aws_public_cert": {
Type: schema.TypeString,
Required: true,
Description: "Base64 encoded AWS Public key required to verify PKCS7 signature of the EC2 instance metadata.",
ForceNew: true,
},
"type": {
Type: schema.TypeString,
Optional: true,
Description: "The type of document that can be verified using the certificate. Must be either \"pkcs7\" or \"identity\".",
ForceNew: true,
Default: "pkcs7",
ValidateFunc: validation.StringInSlice([]string{"pkcs7", "identity"}, false),
},
"backend": {
Type: schema.TypeString,
Optional: true,
Description: "Unique name of the auth backend to configure.",
ForceNew: true,
Default: "aws",
// standardise on no beginning or trailing slashes
StateFunc: func(v interface{}) string {
return strings.Trim(v.(string), "/")
},
},
},
}
}
func awsAuthBackendCertCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
backend := d.Get("backend").(string)
certType := d.Get("type").(string)
publicCert := d.Get("aws_public_cert").(string)
name := d.Get("cert_name").(string)
path := awsAuthBackendCertPath(backend, name)
log.Printf("[DEBUG] Writing cert %q to AWS auth backend", path)
_, err := client.Logical().Write(path, map[string]interface{}{
"aws_public_cert": publicCert,
"type": certType,
})
d.SetId(path)
if err != nil {
d.SetId("")
return fmt.Errorf("Error configuring AWS auth backend cert %q: %s", path, err)
}
log.Printf("[DEBUG] Wrote cert %q to AWS auth backend", path)
return awsAuthBackendCertRead(d, meta)
}
func awsAuthBackendCertRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
path := d.Id()
backend, err := awsAuthBackendCertBackendFromPath(path)
if err != nil {
return fmt.Errorf("Invalid path %q for AWS auth backend cert: %s", path, err)
}
name, err := awsAuthBackendCertNameFromPath(path)
if err != nil {
return fmt.Errorf("Invalid path %q for AWS auth backend cert: %s", path, err)
}
log.Printf("[DEBUG] Reading cert %q from AWS auth backend", path)
resp, err := client.Logical().Read(path)
if err != nil {
return fmt.Errorf("Error reading AWS auth backend cert %q: %s", path, err)
}
log.Printf("[DEBUG] Read cert %q from AWS auth backend", path)
if resp == nil {
log.Printf("[WARN] AWS auth backend cert %q not found, removing it from state", path)
d.SetId("")
return nil
}
// the cert response gets back as undecoded base64
// to keep it simple for people referencing the cert body
// and make sure they get what they expect, we turn it back
// into base64 before putting it in the state
d.Set("aws_public_cert", base64.RawStdEncoding.EncodeToString([]byte(resp.Data["aws_public_cert"].(string))))
d.Set("type", resp.Data["type"])
d.Set("backend", backend)
d.Set("cert_name", name)
return nil
}
func awsAuthBackendCertDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*api.Client)
path := d.Id()
log.Printf("[DEBUG] Removing cert %q from AWS auth backend", path)
_, err := client.Logical().Delete(path)
if err != nil {
return fmt.Errorf("Error deleting AWS auth backend cert %q: %s", path, err)
}
log.Printf("[DEBUG] Removed cert %q from AWS auth backend", path)
return nil
}
func awsAuthBackendCertExists(d *schema.ResourceData, meta interface{}) (bool, error) {
client := meta.(*api.Client)
path := d.Id()
log.Printf("[DEBUG] Checking if cert %q exists in AWS auth backend", path)
resp, err := client.Logical().Read(path)
if err != nil {
return true, fmt.Errorf("Error checking for existence of AWS auth backend cert %q: %s", path, err)
}
log.Printf("[DEBUG] Checked if cert %q exists in AWS auth backend", path)
return resp != nil, nil
}
func awsAuthBackendCertPath(backend, name string) string {
return "auth/" + strings.Trim(backend, "/") + "/config/certificate/" + strings.Trim(name, "/")
}
func awsAuthBackendCertNameFromPath(path string) (string, error) {
if !awsAuthBackendCertNameFromPathRegex.MatchString(path) {
return "", fmt.Errorf("no name found")
}
res := awsAuthBackendCertNameFromPathRegex.FindStringSubmatch(path)
if len(res) != 2 {
return "", fmt.Errorf("unexpected number of matches (%d) for name", len(res))
}
return res[1], nil
}
func awsAuthBackendCertBackendFromPath(path string) (string, error) {
if !awsAuthBackendCertBackendFromPathRegex.MatchString(path) {
return "", fmt.Errorf("no backend found")
}
res := awsAuthBackendCertBackendFromPathRegex.FindStringSubmatch(path)
if len(res) != 2 {
return "", fmt.Errorf("unexpected number of matches (%d) for backend", len(res))
}
return res[1], nil
}