Compare commits

..

3 Commits

3 changed files with 122 additions and 0 deletions

8
.gitignore vendored
View File

@@ -7,3 +7,11 @@ __pycache__/
# Ignore prototype scripts # Ignore prototype scripts
prototype_*.py prototype_*.py
# Shell secrets
*.secret
# Certificate files
*.pem
*.key
*.crt

28
sk/azure.py Normal file
View File

@@ -0,0 +1,28 @@
"""
Minimal Authentication package for Azure.
Uses client credentials - a secret or a certificate.
"""
import os
import requests
def secret_credentials_auth(
scope: str = "https://app.vssps.visualstudio.com/.default",
tenant_id: str = os.environ.get("AZURE_TENANT_ID", ""),
client_id: str = os.environ.get("AZURE_CLIENT_ID", ""),
client_secret: str = os.environ.get("AZURE_CLIENT_SECRET")
) -> str:
"""
Authenticate using client credentials. Pass credentials via environment variables,
or directly as function parameters.
"""
token_url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
r = requests.get(token_url, data={
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": client_secret,
"scope": scope
})
r.raise_for_status()
return r.json().get("access_token", "")

86
sk/certificates.py Normal file
View File

@@ -0,0 +1,86 @@
import datetime
from cryptography.x509 import Name, NameAttribute, CertificateBuilder, BasicConstraints, random_serial_number
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
import pathlib
def create_self_signed_certificate(
file_path: str,
subject_name: str,
organization_name: str,
country_name: str,
valid_days: int = 365,
key_size: int = 2048
):
"""
Create a self-signed certificate. It saves the certificate and private key
in PEM format to the specified file path. Three files are created:
- <file_path>.crt : The public certificate
- <file_path>.key : The private key
- <file_path>.pem : The certificate and private key combined in one file
:param file_path: Base file path to save the certificate and key.
:param subject_name: Common Name (CN) for the certificate.
:param organization_name: Organization Name (O) for the certificate.
:param country_name: Country Name (C) for the certificate.
:param valid_days: Number of days the certificate is valid for.
:param key_size: Size of the RSA key.
Use the following command to replace any credentials already defined for the
App Registration with that certificate:
az ad app credential reset --id <CLIENT_ID> --cert @<file_path>.crt
Use --append to add the certificate without removing existing credentials.
> Note: Do not upload the private key file (.key) nor the combined PEM file (.pem).
"""
key = rsa.generate_private_key(public_exponent=65537, key_size=key_size)
subject = issuer = Name([
NameAttribute(NameOID.COUNTRY_NAME, country_name),
NameAttribute(NameOID.ORGANIZATION_NAME, organization_name),
NameAttribute(NameOID.COMMON_NAME, subject_name),
])
cert = (
CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(key.public_key())
.serial_number(random_serial_number())
.not_valid_before(datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=1))
.not_valid_after(datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=valid_days))
.add_extension(BasicConstraints(ca=True, path_length=None), critical=True)
.sign(key, hashes.SHA256())
)
crt_path = pathlib.Path(file_path).with_suffix('.crt')
key_path = pathlib.Path(file_path).with_suffix('.key')
pem_path = pathlib.Path(file_path).with_suffix('.pem')
public_key = cert.public_bytes(serialization.Encoding.PEM)
private_key = key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
)
# Write the certificate
with open(crt_path, "wb") as f:
f.write(public_key)
# Write the private key
with open(key_path, "wb") as f:
f.write(private_key)
with open(pem_path, "wb") as f:
f.write(public_key)
f.write(private_key)
print(f"Certificate created and saved.")
print(f" - Certificate: {crt_path}")
print(f" - Private Key: {key_path}")
print(f" - PEM File: {pem_path}")