smallstep / certificates

🛡️ A private certificate authority (X.509 & SSH) & ACME server for secure automated certificate management, so you can use TLS everywhere & SSO for SSH.
https://smallstep.com/certificates
Apache License 2.0
6.77k stars 442 forks source link

Include additional data from Cloud Metadata in certificates in disableCustomSAN mode. #1059

Open the-maldridge opened 2 years ago

the-maldridge commented 2 years ago

Hello!

Issue details

When using a cloud provisioner with custom SANs disabled, it would be nice for the issued cert to have all the information from the instance identity document (or equivalent) present in the cert. For example, I might not know what specific instance should be able to be trusted with certain data when presenting a certificate, but I know all images of a particular class can be trusted.

Why is this needed?

This enhancement would further streamline the use case where you use step-ca as a way to bootstrap machine identity in a cloud-agnostic way. When paired with Hashicorp Vault this provides a powerful tool to use one kind of identity document for machines across arbitrary clouds, humans (via an OIDC provisioner) and organizational entities to all use x509 certificates as a common identity document.

maraino commented 2 years ago

I suppose you're referring to the AWS instance identity document, right? It's in the token, but you need to decode it and unmarshal it to access it.

For GCP, it should be accessible using .Token.google.* e.g. .Token.google.compute_engine.instance_name.

For Azure, it's also in the token, but the information they provide is minimal xms_mirid looks like:

/subscriptions/<uuid>/resourcegroups/<group>/providers/Microsoft.Compute/virtualMachines/<name>
or 
/subscriptions/<uuid>/resourcegroups/<group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name>

It totally makes sense to add it, and as we will be adding it for AWS, we should extract the Azure and GCP ones too to the same object so they are easy to read.

maraino commented 2 years ago

FYI, right now you might be able to use sprig functions to access the AWS one.

the-maldridge commented 2 years ago

I'll have to take a look. My immediate use case is with AWS, but I work across all 3 major clouds and a bunch of smaller ones, so an extensible solution here would be ideal.

maraino commented 2 years ago

My idea is to add support for those 3, for example, having access to AWS instance id like .IID.instanceId. But the property names will be specific for each provider.

the-maldridge commented 2 years ago

I think I may not be following here. How would you get from .IID.instanceId to something being set in the certificate?

maraino commented 2 years ago

You can use templates to define the format of the final certificate. Adding an .IID as input data will allow you to use that data in the template.

However, if you use Vault for signing certificates, we don't have a way to send the template attributes to them. Looking at their API, we can get some SANs present after rendering the template and add them to the request, right now we send the CSR and lifetime:

https://github.com/smallstep/certificates/blob/7830c5bd72b9509b3470d4e929b72261c76c452b/cas/vaultcas/vaultcas.go#L212-L219

But, as far as I know, we won't be able to send all things that certificate templates support using Vault.

maraino commented 2 years ago

I'm not a Vault expert, but if you are using it to sign certificates and have an idea of how to do it, please let us know.

the-maldridge commented 2 years ago

Ah I should clarify. I'm using smallstep certificates to authenticate to vault. Every machine can auth to the step-ca using an ACME transaction or in some cases a SCEP transaction, and then they have a machine identity. I think use these certificates to pass to the Vault x509 authentication backend to get a vault token for that machine that I can use to retrieve more secrets and configuration data.

Vault has a way to map policies based on certificate attributes such as hostname or extension, that's what kicked off this whole idea was a way to tell vault that particular classes of machine have a particular grant set of policies in vault.

maraino commented 2 years ago

If I understand this properly, adding, for example, {{ .IID.instanceId }} in the certificate template as a URI or a custom extension, you would be able to get specific secrets for that particular instance. Right?

If that's the case adding that IID attribute to templates is the solution.

the-maldridge commented 2 years ago

yes, that's roughly the idea. My understanding is that the InstanceID is already there. I'm trying to figure out how to get things like the instance image ID out of the IID. It looks like for all 3 clouds the instance ID should be default?

On Fri, Sep 23, 2022 at 2:01 PM Mariano Cano @.***> wrote:

If I understand this properly, adding, for example, {{ .IID.instanceId }} in the certificate template as a URI or a custom extension, you would be able to get specific secrets for that particular instance. Right?

If that's the case adding that IID attribute to templates is the solution.

— Reply to this email directly, view it on GitHub https://github.com/smallstep/certificates/issues/1059#issuecomment-1256571480, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARW3FSJAHOLZ5YS5CF62V3V7X5BFANCNFSM6AAAAAAQQRMOFM . You are receiving this because you authored the thread.Message ID: @.***>

-- the-maldridge @.***

maraino commented 2 years ago

GCP and AWS have that, but Azure is the one that has less information. We should use the names used on each platform, but we can try to use some common attributes for example that instance id, in Azure the identityId can be the name in virtualMachines or userAssignedIdentities.