-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for google_service_account_key #472
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to confirm, this change adds about 70 new vendored files. Is that intentional?
Also, before this is checked in it'll need documentation in the website/ folder.
} | ||
|
||
d.SetId(sak.Name) | ||
d.Set("name", sak.Name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of setting these values on create, we usually call the read function at the end of the create function. Is it possible for you to do that here? Alternatively, if your goal was to avoid an extra API call you could add a helper function that could take the ServiceAccountKey object and do the d.Set calls
Required: true, | ||
ForceNew: true, | ||
}, | ||
"name": &schema.Schema{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're trying to get to a more clear way of ordering fields in the schema, by doing Requireds, then Optionals, then Computeds. Mind doing that here too?
} | ||
|
||
func testAccGoogleServiceAccountKey(account, name string) string { | ||
t := `resource "google_service_account" "acceptance" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for consistency with other resources, can you just start this with the fmt.Sprintf instead of making it a variable?
} | ||
|
||
resource "google_service_account_key" "acceptance" { | ||
service_account_id = "${google_service_account.acceptance.id}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you also want to test some of the other fields? There's some logic regarding pgp keys in your create function so at a minimum I'd like to see that tested, but ideally the other fields as well
resource.TestStep{ | ||
Config: testAccGoogleServiceAccountKey(accountId, displayName), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckGoogleServiceAccountKeyExists("google_service_account_key.acceptance"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can check values with fields with resource.TestCheckResourceAttr
to ensure they have the values you want instead of just that the resource exists
return fmt.Errorf("Error creating service account key: %s", err) | ||
} | ||
|
||
if v, ok := d.GetOk("pgp_key"); ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused about this part, since it's just reading a value from the config, encrypting it, and then storing it back in state. I'm not totally against it, but it does make me cautious since it's not necessarily matching the API. What's the use case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use case is to get GPG_key on output for using it with another tools. If it is possible to have them on outpup without storing it, i'm interesting.
@danawillow I have modified all comment except Adding test on all fields. |
I have open on issue on Google googleapis/google-api-go-client#234 @danawillow can you see help us on google to have the good people? |
I have added a workaroud for waiting public Key. |
|
||
r := &iam.CreateServiceAccountKeyRequest{} | ||
|
||
if v, ok := d.GetOk("key_algorithm"); ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this has a default value, ok
will always be true, and this and the above can be simplified to:
r := &iam.CreateServiceAccountKeyRequest {
KeyAlgorithm: d.Get("key_algorithm").(string),
}
} | ||
|
||
if pubKey == "" { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: extra newline
pubKey = pubkeyInterface.(string) | ||
} | ||
|
||
if pubKey == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this variable never gets used, it might make sense to just not set it at all and instead do an if statement like:
if _, ok := d.GetOk("public_key"); !ok {
// stuff
}
|
||
sak, err := config.clientIAM.Projects.ServiceAccounts.Keys.Create(serviceAccount, r).Do() | ||
if err != nil || sak == nil { | ||
return fmt.Errorf("Error creating service account key: %s", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it might be nice to differentiate in the message the case where it returned an error vs returning nothing
Required: true, | ||
ForceNew: true, | ||
}, | ||
"public_key_type": &schema.Schema{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this value has a reasonable default: https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts.keys/get. Any reason why it's Required
vs private_key_type
and key_algorithm
being Optional?
Optional: true, | ||
ForceNew: true, | ||
}, | ||
"private_key": &schema.Schema{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be down in the Computed
section
|
||
## Import | ||
|
||
Lightsail Key Pairs cannot be imported, because the private and public key are |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's lightsail?
} | ||
``` | ||
|
||
## Argument Reference |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing docs for public_key_type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
|
||
## Attributes Reference | ||
|
||
The following attributes are exported in addition to the arguments listed above: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also valid_after and valid_before
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
* `public_key` - the public key, base64 encoded | ||
* `private_key` - the private key, base64 encoded. This is only populated | ||
when creating a new key, and when no `pgp_key` is provided | ||
* `encrypted_private_key` – the private key material, base 64 encoded and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the schema these are called private_key_encrypted
and private_key_fingerprint
|
||
r.PrivateKeyType = d.Get("private_key_type").(string) | ||
|
||
sak, err := config.clientIAM.Projects.ServiceAccounts.Keys.Create(serviceAccount, r).Do() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused, why do we only call the create function if public_key
is unset?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes of course.
Anything I can do to help speed up this PR? :) Creating service account keys is indispensable to configuring Google Cloud SQL on GKE containers as the Cloud SQL Proxy requires those credentials - otherwise it's not possible to connect from containers within GKE to Google Cloud SQL which in turn makes it impossible to automate the process with terraform at the moment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there!
KeyAlgorithm: d.Get("key_algorithm").(string), | ||
} | ||
|
||
var err error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't have to declare this here since you initialize it just a few lines down with the :=
|
||
var err error | ||
|
||
r.PrivateKeyType = d.Get("private_key_type").(string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also add this into the struct on line 94ish like you did with key_algorithm
} | ||
|
||
err = serviceAccountKeyWaitTime(config.clientIAM.Projects.ServiceAccounts.Keys, d.Id(), d.Get("public_key_type").(string), "Creating Service account key", 4) | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there's an error creating it, we probably want to d.SetId("")
so it doesn't end up in state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actualiy a bug on GCE IAM, the key is is well created but not downloadable just after creation. it is necessary to wait a few second or minut to download it.
The setId is good because key well exist
## Argument Reference | ||
|
||
The following arguments are supported: | ||
* `name` - The name used for this key pair (not used on create) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since name
is computed, it probably belongs in the Attributes Reference
section (and then you can get rid of the parenthetical)
|
||
The following attributes are exported in addition to the arguments listed above: | ||
|
||
* `fingerprint` - The MD5 public key fingerprint as specified in section 4 of RFC 4716. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can you make sure there's a new line between each bullet point?
) | ||
|
||
// Test that a service account key can be created and destroyed | ||
func TestAccGoogleServiceAccountKey_basic(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add t.Parallel() (and then a new line) to the beginning of each of these tests?
public_key_type = "TYPE_X509_PEM_FILE" | ||
pgp_key = <<EOF | ||
%s | ||
EOF |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you have an extra space after the EOF
which is causing the test to fail. If you remove the extra space it passes.
Oh also you'll want to add an entry into |
All change are made. |
if err != nil { | ||
return err | ||
} | ||
resourceGoogleServiceAccountKeyRead(d, meta) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can just be return resourceGoogleServiceAccountKeyRead(d, meta)
and then you can get rid of the rest of the function
"public_key": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
Optional: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this Optional
line should be removed, and this whole field should move into the Computed section
* `public_key` - The public key, base64 encoded | ||
|
||
* `private_key` - The private key, base64 encoded. This is only populated | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: the newline should be after the next line, not before it.
|
||
// Test that a service account key can be created and destroyed | ||
func TestAccGoogleServiceAccountKey_basic(t *testing.T) { | ||
t.Parallel() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: empty line after all t.Parallel()
s
@@ -0,0 +1,85 @@ | |||
--- | |||
layout: "google" | |||
page_title: "Google: google_service_accout_key" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: account
website/google.erb
Outdated
@@ -92,6 +92,10 @@ | |||
<li<%= sidebar_current("docs-google-service-account") %>> | |||
<a href="/docs/providers/google/r/google_service_account.html">google_service_account</a> | |||
</li> | |||
<li<%= sidebar_current("docs-google-service-account") %>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be docs-google-service-account-key
@danawillow All are good |
Thanks @sebglon!
|
Awesome, thank you both for your work on this! Is there a way to check the ETA of unreleased versions (specifically 1.1.2 :) )? |
Our goal is to release every two weeks or so, but we don't give exact dates because sometimes we need the flexibility to release sooner or later. |
Thank you for the swift response, I'm looking forward to having this released! |
Hope this doesn't come by as annoying, but this issue has actually blocked my team and me since it came up. It would be extremely awesome if it was possible to release some time this week, especially because i have no idea how to add custom built plugins to terraform (installed from binaries). |
* Initial support for google service account keys * Add vendor for vault and encryption * Add change for PR comment * Add doc and improvement fo public key management * adding waiter for compatibility with issue googleapis/google-api-go-client#234 * improvement * Add test with pgp_key * Perform doc anf format * remove test if public_key exists * Add link on doc * correct pr
…corp#472) <!-- This change is generated by MagicModules. --> /cc @rileykarson
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 hashibot-feedback@hashicorp.com. Thanks! |
to correct PR #204