Certificate Signing¶
Paramiko-Cloud signs OpenSSH certificates with the same high-level pattern for every provider:
Create a cloud-backed ECDSA certificate authority key.
Provide the public key that should receive a certificate.
Choose principals, validity, certificate type, and options.
Write the returned certificate line to the matching
*-cert.pubfile.
The result is an OpenSSH certificate public key line, not an X.509 certificate. OpenSSH certificates are compact SSH public-key records that bind a subject key to identity, validity, and policy fields signed by a trusted CA key.
Signing a User Certificate¶
This example uses AWS KMS for the certificate authority key, but the
sign_certificate call is the same for AWS, Google Cloud, Azure, and any other
Paramiko key that includes CertificateSigningKeyMixin.
from datetime import timedelta
from paramiko import RSAKey
from paramiko_cloud.aws.keys import ECDSAKey
from paramiko_cloud.pki import CertificateExtensions
ca_key = ECDSAKey(
"arn:aws:kms:us-east-1:012345678901:key/example-key-id",
region_name="us-east-1",
)
subject_key = RSAKey.generate(3072)
cert = ca_key.sign_certificate(
subject_key,
principals=["alice"],
key_id="alice@example.com",
serial=1001,
valid_for=timedelta(hours=8),
extensions={
CertificateExtensions.PERMIT_PTY: "",
CertificateExtensions.PERMIT_AGENT_FORWARDING: "",
},
)
cert_line = cert.cert_string("alice@example.com")
cert_line is an OpenSSH certificate public key line. Save it next to the
subject private key using OpenSSH’s certificate naming convention, such as
id_rsa-cert.pub for id_rsa.
Certificate Parameters¶
sign_certificate accepts principals directly and forwards the remaining
certificate configuration to CertificateParameters.
Common parameters are:
Parameter |
Purpose |
Default |
|---|---|---|
|
User names or host names valid for the certificate. |
Required by |
|
|
|
|
Audit label stored in the certificate. |
Empty string |
|
CA-defined certificate serial number. |
|
|
Unix timestamp when the certificate becomes valid. |
Current time |
|
Unix timestamp when the certificate expires. |
|
|
Duration used when |
One hour |
|
OpenSSH critical options. |
No critical options |
|
OpenSSH extensions. |
All supported extensions enabled by |
The certificate also includes a nonce, the subject public key, the CA public key, and a CA signature over the preceding certificate fields. Paramiko-Cloud handles those wire-format details when it builds the certificate.
OpenSSH treats critical options as mandatory restrictions. If a client or server
does not understand a critical option in a certificate, it must reject that
certificate. Extensions are non-critical grants such as PTY or agent forwarding.
Pass extensions={} when you want a certificate with no extensions.
The standard extension values are empty strings:
extensions = {
CertificateExtensions.PERMIT_PTY: "",
CertificateExtensions.PERMIT_AGENT_FORWARDING: "",
}
Critical option values carry option-specific data:
from paramiko_cloud.pki import CertificateCriticalOptions
critical_options = {
CertificateCriticalOptions.SOURCE_ADDRESS: "10.0.0.0/8,192.0.2.0/24",
}
OpenSSH treats an empty principals list as valid for any principal of the certificate type. Prefer explicit principals for normal user and host certificates.
Signing a Host Certificate¶
Host certificates use the same API with CertificateType.HOST. Principals are
the hostnames or address names that should validate against the host key.
from datetime import timedelta
from paramiko import ECDSAKey as ParamikoECDSAKey
from paramiko_cloud.gcp.keys import ECDSAKey as GCPECDSAKey
from paramiko_cloud.pki import CertificateType
ca_key = GCPECDSAKey(kms_client, key_version_name)
host_key = ParamikoECDSAKey.generate()
host_cert = ca_key.sign_certificate(
host_key,
principals=["web-01.example.com", "10.0.0.15"],
type=CertificateType.HOST,
key_id="web-01",
valid_for=timedelta(days=7),
extensions={},
)
host_cert_line = host_cert.cert_string("web-01.example.com")
Public CA Key¶
Cloud-backed keys can expose their public key in OpenSSH format:
ca_public_key = ca_key.pubkey_string("production-user-ca")
Private key export and local key generation are intentionally disabled for cloud-backed keys. Create and rotate the CA key in the provider’s key management service, then point Paramiko-Cloud at the existing key.
OpenSSH validates the certificate only when the CA public key is trusted by the server for user certificates or by the client for host certificates.
Serializing Signing Requests¶
CertificateSigningRequest can serialize a request to protobuf and reconstruct
it later. This is the format used by the gRPC API.
from paramiko import RSAKey
from paramiko_cloud.pki import (
CertificateParameters,
CertificateSigningRequest,
)
request = CertificateSigningRequest(
RSAKey.generate(3072),
CertificateParameters(principals=["alice"], key_id="alice@example.com"),
)
proto = request.to_proto()
payload = proto.SerializeToString()
restored_proto = type(proto).FromString(payload)
restored = CertificateSigningRequest.from_proto(restored_proto)
cert = restored.sign(ca_key)