-
Notifications
You must be signed in to change notification settings - Fork 102
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 pubkey generation support #11
Conversation
Signed-off-by: French Ben <frenchben@docker.com>
Signed-off-by: French Ben <frenchben@docker.com>
Signed-off-by: French Ben <frenchben@docker.com>
Signed-off-by: French Ben <frenchben@docker.com>
Signed-off-by: French Ben <frenchben@docker.com>
There's a good amount of duplicate code with the |
Hey @FrenchBen, this might also answer your second question as well, but I think this would be better as a data source. Main reason being is that a private key already needs to exist to extract the public key from, so nothing is actually being created by the resource. More specifically answering your question about reuse - you could probably take the extraction code starting here and throw it into a helper that both |
Signed-off-by: French Ben <frenchben@docker.com>
Signed-off-by: French Ben <frenchben@docker.com>
Updated to use a data_source instead, as recommended:
|
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.
@FrenchBen great job so far! Just got some review comments that I'd like to see changed before we merge, and also the resource is lacking documentation. Can you make sure you add that as well?
You can see some examples on existing documentation for this provider in the website
directory, and if you want to preview it you can clone the terraform-website repository and follow the instructions there to get set up.
Thanks!
tls/data_source_public_key.go
Outdated
return &schema.Resource{ | ||
Read: dataSourcePublicKeyRead, | ||
Schema: map[string]*schema.Schema{ | ||
"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.
Can this be changed to private_key_pem
to bring it in line with the other resources in this provider?
tls/data_source_public_key.go
Outdated
Type: schema.TypeString, | ||
Optional: true, | ||
Description: "File path of the PEM formatted string to use as the private key", | ||
ForceNew: 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.
ForceNew
is not needed in data sources. This generally controls deletion/creation workflows, both of which data sources lack.
tls/data_source_public_key.go
Outdated
Description: "PEM formatted string to use as the private key", | ||
}, | ||
|
||
"private_key_path": &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'm actually wondering if maybe this key should just be removed - this removes a bit of complexity from the resource, and if someone needs to load a file from a local path, they can just use the file
interpolation function.
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.
Great point! It'll make things a lot easier.
tls/data_source_public_key.go
Outdated
|
||
func dataSourcePublicKeyRead(d *schema.ResourceData, meta interface{}) error { | ||
// Read private key | ||
bytes := []byte(d.Get("private_key").(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 could also use GetOk
or GetOkExists
here, which are specifically the exact ways you check for a value defined in Terraform.
tls/data_source_public_key.go
Outdated
keyPemBlock, _ := pem.Decode(bytes) | ||
|
||
if keyPemBlock == nil || (keyPemBlock.Type != "RSA PRIVATE KEY" && keyPemBlock.Type != "EC PRIVATE KEY") { | ||
return fmt.Errorf("failed to decode PEM block containing RSA private 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.
The error message seems to indicate that you are only attempting to decode an RSA private key even though the key can be that or an EC private key.
tls/data_source_public_key.go
Outdated
return fmt.Errorf("error converting key to rsa %s", err) | ||
} | ||
|
||
d.Set("private_key_pem", keyPem) |
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 you have the field here named private_key_pem
even though the field is just private_key
in the schema. I'm recommending the schema be fixed, of course. :)
tls/util.go
Outdated
@@ -74,3 +75,29 @@ func parseCertificateRequest(d *schema.ResourceData, pemKey string) (*x509.Certi | |||
|
|||
return certReq, nil | |||
} | |||
|
|||
func parsePublicKey(d *schema.ResourceData, rsaKey interface{}) 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.
Minor can we change this to readPublicKey
to imply that it's doing a bit more than just parsing the public key?
} | ||
|
||
const testAccDataSourcePublicKeyConfig = ` | ||
data "tls_public_key" "test" { |
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.
PS: You could probably make this test self-hosting but using the tls_private_key
resource to generate a key. Then you could use TestCheckResourceAttrPair
to just compare the two values.
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'll add it as another test. I like the fact that we're taking a private key without it's matching Public Key and confirming that its output is what we expected.
The TestCheckResourceAttrPair
seems redundant, as they both use the same function, thus if there's a mistake, it'll come be a consistent one.
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.
@FrenchBen fair enough, and I actually didn't notice the testPrivateKey
fixture being used in other tests. Will wait for the second test!
Signed-off-by: French Ben <frenchben@docker.com>
Signed-off-by: French Ben <frenchben@docker.com>
@vancluever PTAL at the latest changes :) |
@FrenchBen sorry for leaving this so long - I'll have a look sometime within the next couple of days for sure. Were you going to work on adding the second test as mentioned? |
@vancluever already did: The 2 tests are:
Anything else you think I should test for? |
Great - I didn't see that! Barring anything serious, I think this can be merged tomorrow when I give it another once over 🙂 |
I think it's my fault - Looks like spacing is a little off, I'll get this fixed. |
Signed-off-by: French Ben <frenchben@docker.com>
b762db2
to
de96279
Compare
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.
Hey @FrenchBen, one more comment about the tests, in addition to the following smoke test that failed:
This config:
resource "tls_private_key" "key" {
algorithm = "ECDSA"
ecdsa_curve = "P384"
}
data "tls_public_key" "pub" {
private_key_pem = "${tls_private_key.key.private_key_pem}"
}
output "data_public_key_pem" {
value = "${data.tls_public_key.pub.public_key_pem}"
}
output "data_public_key_openssh" {
value = "${data.tls_public_key.pub.public_key_openssh}"
}
Gives this error:
Error: Error applying plan:
1 error(s) occurred:
* data.tls_public_key.pub: data.tls_public_key.pub: error converting key to rsa asn1: structure error: tags don't match (2 vs {class:0 tag:4 length:48 isCompound:false}) {optional:false explicit:false application:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} @5
This works with RSA, so not too sure what's happening here, but the P384 test is what is in our examples for tls_private_key
, and the public keys dump in that resource just fine.
If you can fix that it would be great (might be good to add another test with that config specifically), also you will need to pull as I just fixed up some test naming and docs, and was about to approve this before the smoke test failed.
Thanks!
tls/data_source_public_key_test.go
Outdated
resource "tls_private_key" "test" { | ||
algorithm = "RSA" | ||
} | ||
output "private_key_pem" { |
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.
Are these outputs actually being tested anywhere? I don't see any checks for them...
Can this test also be broken out into another test? As it's pretty much a completely different test case (manually supplied key versus generated one).
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.
The output can be removed indeed.
Since the test was for all Public Key, I thought they belonged within the same function, but as separate steps. Is that not the right approach?
Signed-off-by: French Ben <frenchben@docker.com>
Added the extra test - Different algo = different parser (of course 🤦♂️ ) - Moved to using the default private key parser in the certs to make things cleaner. |
@FrenchBen this looks good! I've just split out the tests so that it's more clear what exactly we are testing in each step. Otherwise, this fixed everything - smoke test works now, so I think we are good to merge! Thank you very much for you contribution and your patience through the process! |
I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions. |
Although this may not be very common, I often find myself having to feed a private key to Terraform, but then needing its public key for provider specific deployments.
This adds an equivalent public key RSA generator to the current private key, and moves the
publicKey
function to the public key file.The input is a private key string, or file.
Checking acceptance tests: