Skip to content

Commit 0ed9093

Browse files
drebesmodular-magician
authored andcommitted
[WIP] binary_authorization_attestor KMS support
Signed-off-by: Modular Magician <[email protected]>
1 parent a7a9b85 commit 0ed9093

5 files changed

+353
-13
lines changed

google/bootstrap_utils_test.go

+20-6
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,28 @@ type bootstrappedKMS struct {
1818
*cloudkms.CryptoKey
1919
}
2020

21-
// BootstrapKMSKey returns a KMS key in the "global" location.
22-
// See BootstrapKMSKeyInLocation.
21+
// BootstrapKMSKeyWithPurposeAlgorithm returns a KMS key in the "global" location.
22+
// See BootstrapKMSKeyWithPurposeAlgorithmInLocation.
23+
func BootstrapKMSKeyWithPurposeAlgorithm(t *testing.T, purpose, algorithm string) bootstrappedKMS {
24+
return BootstrapKMSKeyWithPurposeAlgorithmInLocation(t, purpose, algorithm, "global")
25+
}
26+
2327
func BootstrapKMSKey(t *testing.T) bootstrappedKMS {
2428
return BootstrapKMSKeyInLocation(t, "global")
2529
}
2630

2731
/**
28-
* BootstrapKMSKeyWithLocation will return a KMS key in a particular location
29-
* that can be used in tests that are testing KMS integration with other resources.
32+
* BootstrapKMSKeyWithPurposeAlgorithmWithLocation will return a KMS key in a
33+
* particular location with the given purpose and alogrithm that can be used
34+
* in tests that are testing KMS integration with other resources.
3035
*
3136
* This will either return an existing key or create one if it hasn't been created
3237
* in the project yet. The motivation is because keyrings don't get deleted and we
3338
* don't want a linear growth of disabled keyrings in a project. We also don't want
3439
* to incur the overhead of creating a new project for each test that needs to use
3540
* a KMS key.
3641
**/
37-
func BootstrapKMSKeyInLocation(t *testing.T, locationID string) bootstrappedKMS {
42+
func BootstrapKMSKeyWithPurposeAlgorithmInLocation(t *testing.T, purpose, algorithm, locationID string) bootstrappedKMS {
3843
if v := os.Getenv("TF_ACC"); v == "" {
3944
log.Println("Acceptance tests and bootstrapping skipped unless env 'TF_ACC' set")
4045

@@ -87,8 +92,13 @@ func BootstrapKMSKeyInLocation(t *testing.T, locationID string) bootstrappedKMS
8792
cryptoKey, err := kmsClient.Projects.Locations.KeyRings.CryptoKeys.Get(keyName).Do()
8893
if err != nil {
8994
if isGoogleApiErrorWithCode(err, 404) {
95+
newTemplate := cloudkms.CryptoKeyVersionTemplate{
96+
Algorithm: algorithm,
97+
}
98+
9099
newKey := cloudkms.CryptoKey{
91-
Purpose: "ENCRYPT_DECRYPT",
100+
Purpose: purpose,
101+
VersionTemplate: &newTemplate,
92102
}
93103

94104
cryptoKey, err = kmsClient.Projects.Locations.KeyRings.CryptoKeys.Create(keyParent, &newKey).
@@ -112,6 +122,10 @@ func BootstrapKMSKeyInLocation(t *testing.T, locationID string) bootstrappedKMS
112122
}
113123
}
114124

125+
func BootstrapKMSKeyInLocation(t *testing.T, locationID string) bootstrappedKMS {
126+
return BootstrapKMSKeyWithPurposeAlgorithmInLocation(t, "ENCRYPT_DECRYPT", "GOOGLE_SYMMETRIC_ENCRYPTION", locationID)
127+
}
128+
115129
var serviceAccountEmail = "tf-bootstrap-service-account"
116130
var serviceAccountDisplay = "Bootstrapped Service Account for Terraform tests"
117131

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package google
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"strconv"
7+
"strings"
8+
9+
"github.com/hashicorp/terraform/helper/schema"
10+
)
11+
12+
func dataSourceGoogleKmsCryptoKeyVersion() *schema.Resource {
13+
return &schema.Resource{
14+
Read: dataSourceGoogleKmsCryptoKeyVersionRead,
15+
Schema: map[string]*schema.Schema{
16+
"crypto_key": {
17+
Type: schema.TypeString,
18+
Required: true,
19+
ForceNew: true,
20+
},
21+
"version": {
22+
Type: schema.TypeInt,
23+
Optional: true,
24+
Default: 1,
25+
},
26+
"algorithm": {
27+
Type: schema.TypeString,
28+
Computed: true,
29+
},
30+
"protection_level": {
31+
Type: schema.TypeString,
32+
Computed: true,
33+
},
34+
"state": {
35+
Type: schema.TypeString,
36+
Computed: true,
37+
},
38+
"public_key": {
39+
Type: schema.TypeList,
40+
Optional: true,
41+
MaxItems: 1,
42+
Elem: &schema.Resource{
43+
Schema: map[string]*schema.Schema{
44+
"algorithm": {
45+
Type: schema.TypeString,
46+
Computed: true,
47+
},
48+
"pem": {
49+
Type: schema.TypeString,
50+
Computed: true,
51+
},
52+
},
53+
},
54+
},
55+
},
56+
}
57+
}
58+
59+
func dataSourceGoogleKmsCryptoKeyVersionRead(d *schema.ResourceData, meta interface{}) error {
60+
config := meta.(*Config)
61+
62+
url, err := replaceVars(d, config, "{{KmsBasePath}}{{crypto_key}}/cryptoKeyVersions/{{version}}")
63+
if err != nil {
64+
return err
65+
}
66+
67+
log.Printf("[DEBUG] Getting attributes for CryptoKeyVersion: %#v", url)
68+
res, err := sendRequest(config, "GET", url, nil)
69+
if err != nil {
70+
return handleNotFoundError(err, d, fmt.Sprintf("KmsCryptoKeyVersion %q", d.Id()))
71+
}
72+
73+
if err := d.Set("version", flattenKmsCryptoKeyVersionVersion(res["name"], d)); err != nil {
74+
return fmt.Errorf("Error reading CryptoKeyVersion: %s", err)
75+
}
76+
if err := d.Set("state", flattenKmsCryptoKeyVersionState(res["state"], d)); err != nil {
77+
return fmt.Errorf("Error reading CryptoKeyVersion: %s", err)
78+
}
79+
if err := d.Set("protection_level", flattenKmsCryptoKeyVersionProtectionLevel(res["protectionLevel"], d)); err != nil {
80+
return fmt.Errorf("Error reading CryptoKeyVersion: %s", err)
81+
}
82+
if err := d.Set("algorithm", flattenKmsCryptoKeyVersionAlgorithm(res["algorithm"], d)); err != nil {
83+
return fmt.Errorf("Error reading CryptoKeyVersion: %s", err)
84+
}
85+
86+
url, err = replaceVars(d, config, "{{KmsBasePath}}{{crypto_key}}")
87+
if err != nil {
88+
return err
89+
}
90+
91+
log.Printf("[DEBUG] Getting purpose of CryptoKey: %#v", url)
92+
res, err = sendRequest(config, "GET", url, nil)
93+
if err != nil {
94+
return handleNotFoundError(err, d, fmt.Sprintf("KmsCryptoKey %q", d.Id()))
95+
}
96+
97+
if res["purpose"] == "ASYMMETRIC_SIGN" || res["purpose"] == "ASYMMETRIC_DECRYPT" {
98+
url, err = replaceVars(d, config, "{{KmsBasePath}}{{crypto_key}}/cryptoKeyVersions/{{version}}/publicKey")
99+
if err != nil {
100+
return err
101+
}
102+
log.Printf("[DEBUG] Getting public key of CryptoKeyVersion: %#v", url)
103+
res, err = sendRequest(config, "GET", url, nil)
104+
105+
if err := d.Set("public_key", flattenKmsCryptoKeyVersionPublicKey(res, d)); err != nil {
106+
return fmt.Errorf("Error reading CryptoKeyVersion public key: %s", err)
107+
}
108+
}
109+
d.SetId(fmt.Sprintf("//cloudkms.googleapis.com/%s/cryptoKeyVersions/%d", d.Get("crypto_key"), d.Get("version")))
110+
111+
return nil
112+
}
113+
114+
func flattenKmsCryptoKeyVersionVersion(v interface{}, d *schema.ResourceData) interface{} {
115+
parts := strings.Split(v.(string), "/")
116+
version := parts[len(parts)-1]
117+
// Handles the string fixed64 format
118+
if intVal, err := strconv.ParseInt(version, 10, 64); err == nil {
119+
return intVal
120+
} // let terraform core handle it if we can't convert the string to an int.
121+
log.Printf("[DEBUG] Setting Version: %#v", v)
122+
return v
123+
}
124+
125+
func flattenKmsCryptoKeyVersionState(v interface{}, d *schema.ResourceData) interface{} {
126+
log.Printf("[DEBUG] Setting State: %#v", v)
127+
return v
128+
}
129+
130+
func flattenKmsCryptoKeyVersionProtectionLevel(v interface{}, d *schema.ResourceData) interface{} {
131+
log.Printf("[DEBUG] Setting Level: %#v", v)
132+
return v
133+
}
134+
135+
func flattenKmsCryptoKeyVersionAlgorithm(v interface{}, d *schema.ResourceData) interface{} {
136+
return v
137+
}
138+
139+
func flattenKmsCryptoKeyVersionPublicKey(v interface{}, d *schema.ResourceData) interface{} {
140+
if v == nil {
141+
return nil
142+
}
143+
original := v.(map[string]interface{})
144+
if len(original) == 0 {
145+
return nil
146+
}
147+
transformed := make(map[string]interface{})
148+
transformed["pem"] =
149+
flattenKmsCryptoKeyVersionPublicKeyPem(original["pem"], d)
150+
transformed["algorithm"] =
151+
flattenKmsCryptoKeyVersionPublicKeyAlgorithm(original["algorithm"], d)
152+
return []interface{}{transformed}
153+
}
154+
func flattenKmsCryptoKeyVersionPublicKeyPem(v interface{}, d *schema.ResourceData) interface{} {
155+
return v
156+
}
157+
158+
func flattenKmsCryptoKeyVersionPublicKeyAlgorithm(v interface{}, d *schema.ResourceData) interface{} {
159+
return v
160+
}

google/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ func Provider() terraform.ResourceProvider {
178178
"google_kms_secret": dataSourceGoogleKmsSecret(),
179179
"google_kms_key_ring": dataSourceGoogleKmsKeyRing(),
180180
"google_kms_crypto_key": dataSourceGoogleKmsCryptoKey(),
181+
"google_kms_crypto_key_version": dataSourceGoogleKmsCryptoKeyVersion(),
181182
"google_folder": dataSourceGoogleFolder(),
182183
"google_folder_organization_policy": dataSourceGoogleFolderOrganizationPolicy(),
183184
"google_netblock_ip_ranges": dataSourceGoogleNetblockIpRanges(),

google/resource_binary_authorization_attestor.go

+84-2
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,32 @@ func resourceBinaryAuthorizationAttestor() *schema.Resource {
6161
Schema: map[string]*schema.Schema{
6262
"ascii_armored_pgp_public_key": {
6363
Type: schema.TypeString,
64-
Required: true,
64+
Optional: true,
6565
},
6666
"comment": {
6767
Type: schema.TypeString,
6868
Optional: true,
6969
},
7070
"id": {
7171
Type: schema.TypeString,
72-
Computed: true,
72+
Optional: true,
73+
},
74+
"pkix_public_key": {
75+
Type: schema.TypeList,
76+
Optional: true,
77+
MaxItems: 1,
78+
Elem: &schema.Resource{
79+
Schema: map[string]*schema.Schema{
80+
"public_key_pem": {
81+
Type: schema.TypeString,
82+
Optional: true,
83+
},
84+
"signature_algorithm": {
85+
Type: schema.TypeString,
86+
Optional: true,
87+
},
88+
},
89+
},
7390
},
7491
},
7592
},
@@ -320,6 +337,7 @@ func flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeys(v inte
320337
"comment": flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysComment(original["comment"], d),
321338
"id": flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysId(original["id"], d),
322339
"ascii_armored_pgp_public_key": flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysAsciiArmoredPgpPublicKey(original["asciiArmoredPgpPublicKey"], d),
340+
"pkix_public_key": flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKey(original["pkixPublicKey"], d),
323341
})
324342
}
325343
return transformed
@@ -336,6 +354,29 @@ func flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysAsciiAr
336354
return v
337355
}
338356

357+
func flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKey(v interface{}, d *schema.ResourceData) interface{} {
358+
if v == nil {
359+
return nil
360+
}
361+
original := v.(map[string]interface{})
362+
if len(original) == 0 {
363+
return nil
364+
}
365+
transformed := make(map[string]interface{})
366+
transformed["public_key_pem"] =
367+
flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKeyPublicKeyPem(original["publicKeyPem"], d)
368+
transformed["signature_algorithm"] =
369+
flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKeySignatureAlgorithm(original["signatureAlgorithm"], d)
370+
return []interface{}{transformed}
371+
}
372+
func flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKeyPublicKeyPem(v interface{}, d *schema.ResourceData) interface{} {
373+
return v
374+
}
375+
376+
func flattenBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKeySignatureAlgorithm(v interface{}, d *schema.ResourceData) interface{} {
377+
return v
378+
}
379+
339380
func flattenBinaryAuthorizationAttestorAttestationAuthorityNoteDelegationServiceAccountEmail(v interface{}, d *schema.ResourceData) interface{} {
340381
return v
341382
}
@@ -426,6 +467,13 @@ func expandBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeys(v inter
426467
transformed["asciiArmoredPgpPublicKey"] = transformedAsciiArmoredPgpPublicKey
427468
}
428469

470+
transformedPkixPublicKey, err := expandBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKey(original["pkix_public_key"], d, config)
471+
if err != nil {
472+
return nil, err
473+
} else if val := reflect.ValueOf(transformedPkixPublicKey); val.IsValid() && !isEmptyValue(val) {
474+
transformed["pkixPublicKey"] = transformedPkixPublicKey
475+
}
476+
429477
req = append(req, transformed)
430478
}
431479
return req, nil
@@ -443,6 +491,40 @@ func expandBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysAsciiArm
443491
return v, nil
444492
}
445493

494+
func expandBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKey(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
495+
l := v.([]interface{})
496+
if len(l) == 0 || l[0] == nil {
497+
return nil, nil
498+
}
499+
raw := l[0]
500+
original := raw.(map[string]interface{})
501+
transformed := make(map[string]interface{})
502+
503+
transformedPublicKeyPem, err := expandBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKeyPublicKeyPem(original["public_key_pem"], d, config)
504+
if err != nil {
505+
return nil, err
506+
} else if val := reflect.ValueOf(transformedPublicKeyPem); val.IsValid() && !isEmptyValue(val) {
507+
transformed["publicKeyPem"] = transformedPublicKeyPem
508+
}
509+
510+
transformedSignatureAlgorithm, err := expandBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKeySignatureAlgorithm(original["signature_algorithm"], d, config)
511+
if err != nil {
512+
return nil, err
513+
} else if val := reflect.ValueOf(transformedSignatureAlgorithm); val.IsValid() && !isEmptyValue(val) {
514+
transformed["signatureAlgorithm"] = transformedSignatureAlgorithm
515+
}
516+
517+
return transformed, nil
518+
}
519+
520+
func expandBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKeyPublicKeyPem(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
521+
return v, nil
522+
}
523+
524+
func expandBinaryAuthorizationAttestorAttestationAuthorityNotePublicKeysPkixPublicKeySignatureAlgorithm(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
525+
return v, nil
526+
}
527+
446528
func expandBinaryAuthorizationAttestorAttestationAuthorityNoteDelegationServiceAccountEmail(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
447529
return v, nil
448530
}

0 commit comments

Comments
 (0)