Skip to content
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

acme: deprecate gen_ss_cert(), introduce replacement make_self_signed_cert() #9909

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

wgreenberg
Copy link
Collaborator

The goal here was to remove any uses of deprecated pyOpenSSL API, but to do that, we're going to also have to deprecate gen_ss_cert, whose signature includes deprecated types. This also adds a new function, make_self_signed_cert(), with a nearly identical signature and functionality, but accepts cryptography extension types.

Closes #9828

gen_ss_cert includes deprecated pyOpenSSL API in its function signature,
so we can't update it without breaking backwards compatibility. A new
function, make_self_signed_cert, with nearly identical signature (except
for its use of cryptography's extension types) is added for users to
migrate to.
Also generally switch to using `cryptography` types internally where
possible, and switch to the new make_self_signed_cert function.
@wgreenberg wgreenberg marked this pull request as ready for review March 26, 2024 18:56
@wgreenberg
Copy link
Collaborator Author

aaand this is finally ready for review. Unsure if we need to bump the current pinned cryptography version, since it's currently just pegged to != 37.0.3, which is behind the oldest version now

csr = crypto.X509Req()
sanlist = []
# builder.sign(...) below will error out if this isn't the correct private key type
private_key: CertificateIssuerPrivateKeyTypes = cast(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation recommends checking the returned key type rather than casting. We know it's only going to be one of two types, right? So we can do the isinstance for those and error out with a helpful message if it's not one of those. Who was yelling about the potential error, mypy? Because I don't know how we would have hit it if we were loading actual key files, that would be weird and bad.

@@ -410,7 +411,7 @@ class TLSALPN01Response(KeyAuthorizationChallengeResponse):

"""

ID_PE_ACME_IDENTIFIER_V1 = b"1.3.6.1.5.5.7.1.30.1"
ID_PE_ACME_IDENTIFIER_V1 = "1.3.6.1.5.5.7.1.30.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm...not sure we can change this before the major version update? I could see someone calling it and now hitting a type error. isn't all of acme in the public stable interface?

if ext.get_short_name() == b'UNDEF':
data = ext.get_data()
return data == self.h
crypto_cert = cert.to_cryptography()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it's worth it to fully switch to using cryptography instead of crypto while we're here (making breaking changes)? The note at the top of pyopenssl's crypto docs page makes it seem like it might all go away at some point, even if it isn't deprecated yet. Especially since we immediately convert to cryptography internally in this method. But maybe not worth completely removing it now, especially all at once. I know this would be a lot more work, really just thinking out loud here.

extensions: Optional[List[x509.Extension]] = None,
ips: Optional[List[Union[ipaddress.IPv4Address,
ipaddress.IPv6Address]]] = None
) -> crypto.X509:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to my comment above...while we're migrating, could it make sense to return a cryptography.X509.certificate instead in our new method? Or would that be very annoying to thread through things?

if not isinstance(cryptography_priv, (DSAPrivateKey, RSAPrivateKey)):
raise errors.Error("key must be a private key")
cryptography_pub = cryptography_priv.public_key()
builder = builder.public_key(cryptography_pub)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to explicitly set the version like we do in gen_ss_cert?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It always issues V3 certs.

else:
raise ValueError('Invalid key type: {0}'.format(key_type))

with open(key_path, 'wb') as file_h:
file_h.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key))
# TODO ensure this is exactly the same format that pyOpenSSL uses
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noting TODO

@@ -67,7 +67,7 @@ ndg-httpsclient = "0.3.2"
parsedatetime = "2.4"
pbr = "1.8.0"
ply = "3.4"
pyOpenSSL = "17.5.0"
pyOpenSSL = "24.1.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What new functionality of pyOpenSSL/cryptography are we using that requires us to bump this? I thought the point of this PR was that things were being deprecated in newer versions. Will we no longer work with the old versions after this change?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove deprecated uses of OpenSSL.crypto.X509Extension
3 participants