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

Rename CertificateCredential's certificate_bytes -> certificate_data #17090

Merged
merged 2 commits into from
Mar 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion sdk/identity/azure-identity/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Release History

## 1.6.0b2 (Unreleased)

### Breaking Changes
> These changes do not impact the API of stable versions such as 1.5.0.
> Only code written against a beta version such as 1.6.0b1 may be affected.
- Renamed `CertificateCredential` keyword argument `certificate_bytes` to
`certificate_data`

## 1.6.0b1 (2021-02-09)
### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ class CertificateCredential(ClientCredentialBase):
:param str tenant_id: ID of the service principal's tenant. Also called its 'directory' ID.
:param str client_id: the service principal's client ID
:param str certificate_path: path to a PEM-encoded certificate file including the private key. If not provided,
`certificate_bytes` is required.
`certificate_data` is required.

:keyword str authority: Authority of an Azure Active Directory endpoint, for example 'login.microsoftonline.com',
the authority for Azure Public Cloud (which is the default). :class:`~azure.identity.AzureAuthorityHosts`
defines authorities for other clouds.
:keyword bytes certificate_bytes: the bytes of a certificate in PEM format, including the private key
:keyword bytes certificate_data: the bytes of a certificate in PEM format, including the private key
:keyword password: The certificate's password. If a unicode string, it will be encoded as UTF-8. If the certificate
requires a different encoding, pass appropriately encoded bytes instead.
:paramtype password: str or bytes
Expand Down Expand Up @@ -68,34 +68,34 @@ def extract_cert_chain(pem_bytes):
return b"".join(chain.splitlines())


def get_client_credential(certificate_path, password=None, certificate_bytes=None, send_certificate_chain=False, **_):
def get_client_credential(certificate_path, password=None, certificate_data=None, send_certificate_chain=False, **_):
# type: (Optional[str], Optional[Union[bytes, str]], Optional[bytes], bool, **Any) -> dict
"""Load a certificate from a filesystem path or bytes, return it as a dict suitable for msal.ClientApplication"""

if certificate_path:
with open(certificate_path, "rb") as f:
certificate_bytes = f.read()
elif not certificate_bytes:
raise ValueError('CertificateCredential requires a value for "certificate_path" or "certificate_bytes"')
certificate_data = f.read()
elif not certificate_data:
raise ValueError('CertificateCredential requires a value for "certificate_path" or "certificate_data"')

if isinstance(password, six.text_type):
password = password.encode(encoding="utf-8")

private_key = serialization.load_pem_private_key(certificate_bytes, password=password, backend=default_backend())
private_key = serialization.load_pem_private_key(certificate_data, password=password, backend=default_backend())
if not isinstance(private_key, RSAPrivateKey):
raise ValueError("CertificateCredential requires an RSA private key because it uses RS256 for signing")

cert = x509.load_pem_x509_certificate(certificate_bytes, default_backend())
cert = x509.load_pem_x509_certificate(certificate_data, default_backend())
fingerprint = cert.fingerprint(hashes.SHA1()) # nosec

client_credential = {"private_key": certificate_bytes, "thumbprint": hexlify(fingerprint).decode("utf-8")}
client_credential = {"private_key": certificate_data, "thumbprint": hexlify(fingerprint).decode("utf-8")}
if password:
client_credential["passphrase"] = password

if send_certificate_chain:
try:
# the JWT needs the whole chain but load_pem_x509_certificate deserializes only the signing cert
chain = extract_cert_chain(certificate_bytes)
chain = extract_cert_chain(certificate_data)
client_credential["public_certificate"] = six.ensure_str(chain)
except ValueError as ex:
# we shouldn't land here--cryptography already loaded the cert and would have raised if it were malformed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ class CertificateCredential(AsyncContextManager):
:param str tenant_id: ID of the service principal's tenant. Also called its 'directory' ID.
:param str client_id: the service principal's client ID
:param str certificate_path: path to a PEM-encoded certificate file including the private key. If not provided,
`certificate_bytes` is required.
`certificate_data` is required.

:keyword str authority: Authority of an Azure Active Directory endpoint, for example 'login.microsoftonline.com',
the authority for Azure Public Cloud (which is the default). :class:`~azure.identity.AzureAuthorityHosts`
defines authorities for other clouds.
:keyword bytes certificate_bytes: the bytes of a certificate in PEM format, including the private key
:keyword bytes certificate_data: the bytes of a certificate in PEM format, including the private key
:keyword password: The certificate's password. If a unicode string, it will be encoded as UTF-8. If the certificate
requires a different encoding, pass appropriately encoded bytes instead.
:paramtype password: str or bytes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def test_non_rsa_key():
with pytest.raises(ValueError, match=".*RS256.*"):
CertificateCredential("tenant-id", "client-id", EC_CERT_PATH)
with pytest.raises(ValueError, match=".*RS256.*"):
CertificateCredential("tenant-id", "client-id", certificate_bytes=open(EC_CERT_PATH, "rb").read())
CertificateCredential("tenant-id", "client-id", certificate_data=open(EC_CERT_PATH, "rb").read())


def test_tenant_id_validation():
Expand Down Expand Up @@ -145,9 +145,9 @@ def test_requires_certificate():
with pytest.raises(ValueError):
CertificateCredential("tenant", "client-id", certificate_path="")
with pytest.raises(ValueError):
CertificateCredential("tenant", "client-id", certificate_bytes=None)
CertificateCredential("tenant", "client-id", certificate_data=None)
with pytest.raises(ValueError):
CertificateCredential("tenant", "client-id", certificate_path="", certificate_bytes=None)
CertificateCredential("tenant", "client-id", certificate_path="", certificate_data=None)


@pytest.mark.parametrize("cert_path,cert_password", BOTH_CERTS)
Expand Down Expand Up @@ -190,7 +190,7 @@ def mock_send(request, **kwargs):
cred = CertificateCredential(
tenant_id,
client_id,
certificate_bytes=cert_bytes,
certificate_data=cert_bytes,
password=cert_password,
transport=Mock(send=mock_send),
authority=authority,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def test_non_rsa_key():
with pytest.raises(ValueError, match=".*RS256.*"):
CertificateCredential("tenant-id", "client-id", EC_CERT_PATH)
with pytest.raises(ValueError, match=".*RS256.*"):
CertificateCredential("tenant-id", "client-id", certificate_bytes=open(EC_CERT_PATH, "rb").read())
CertificateCredential("tenant-id", "client-id", certificate_data=open(EC_CERT_PATH, "rb").read())


def test_tenant_id_validation():
Expand Down Expand Up @@ -141,9 +141,9 @@ def test_requires_certificate():
with pytest.raises(ValueError):
CertificateCredential("tenant", "client-id", certificate_path="")
with pytest.raises(ValueError):
CertificateCredential("tenant", "client-id", certificate_bytes=None)
CertificateCredential("tenant", "client-id", certificate_data=None)
with pytest.raises(ValueError):
CertificateCredential("tenant", "client-id", certificate_path="", certificate_bytes=None)
CertificateCredential("tenant", "client-id", certificate_path="", certificate_data=None)


@pytest.mark.asyncio
Expand Down Expand Up @@ -177,7 +177,7 @@ async def mock_send(request, **kwargs):
cred = CertificateCredential(
tenant_id,
client_id,
certificate_bytes=cert_bytes,
certificate_data=cert_bytes,
password=cert_password,
transport=Mock(send=mock_send),
authority=authority,
Expand Down
4 changes: 2 additions & 2 deletions sdk/identity/azure-identity/tests/test_live.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ def test_certificate_credential(live_certificate):
)
get_token(credential)

credential = CertificateCredential(tenant_id, client_id, certificate_bytes=live_certificate["cert_bytes"])
credential = CertificateCredential(tenant_id, client_id, certificate_data=live_certificate["cert_bytes"])
get_token(credential)

credential = CertificateCredential(
tenant_id,
client_id,
certificate_bytes=live_certificate["cert_with_password_bytes"],
certificate_data=live_certificate["cert_with_password_bytes"],
password=live_certificate["password"],
)
get_token(credential)
Expand Down
4 changes: 2 additions & 2 deletions sdk/identity/azure-identity/tests/test_live_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ async def test_certificate_credential(live_certificate):
)
await get_token(credential)

credential = CertificateCredential(tenant_id, client_id, certificate_bytes=live_certificate["cert_bytes"])
credential = CertificateCredential(tenant_id, client_id, certificate_data=live_certificate["cert_bytes"])
await get_token(credential)

credential = CertificateCredential(
tenant_id,
client_id,
certificate_bytes=live_certificate["cert_with_password_bytes"],
certificate_data=live_certificate["cert_with_password_bytes"],
password=live_certificate["password"],
)
await get_token(credential)
Expand Down