certificates icon indicating copy to clipboard operation
certificates copied to clipboard

step-ca awskms init with existing KMS key

Open hongkongkiwi opened this issue 4 years ago • 3 comments
trafficstars

I have some pre-setup keys in AWS, I want to use these for smallstep.

It appears that step-awskms-init wants to use it's own key names and won't allow me to specify them. It also doesn't allow me to use existing keys by passing the id.

How would I init my step-ca instance without having atep-awskms-init to create the keys?

hongkongkiwi avatar Nov 15 '21 11:11 hongkongkiwi

If you already have the keys on AWSKMS and you want to sign an intermediate with it, you can modify step-awskms-init removing the creation of the keys, and changing the input of CreateSigner with something like:

signer, err := c.CreateSigner(&apiv1.CreateSignerRequest{
	SigningKey: "awskms:key-id=3d735869-d693-48a0-9682-4bcfabf8703a",
})
if err != nil {
	return err
}

Where 3d735869-d693-48a0-9682-4bcfabf8703a should be the key id for your root key.

maraino avatar Nov 15 '21 19:11 maraino

Thanks that's helpful!

So far here's what I've got:

  signer, err := c.CreateSigner(&apiv1.CreateSignerRequest{
    SigningKey: "awskms:key-id=<my key id>",
  })
  if err != nil {
    return err
  }
  
  	now := time.Now()
	root := &x509.Certificate{
		IsCA:                  true,
		NotBefore:             now,
		NotAfter:              now.Add(time.Hour * 24 * 365 * 10),
		KeyUsage:              x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
		BasicConstraintsValid: true,
		MaxPathLen:            1,
		MaxPathLenZero:        false,
		Issuer:                pkix.Name{CommonName: "My Root CA (Development)"},
		Subject:               pkix.Name{CommonName: "My Root CA (Development)"},
		SerialNumber:          mustSerialNumber(),
		SubjectKeyId:          mustSubjectKeyID(signer.Public()),
		AuthorityKeyId:        mustSubjectKeyID(signer.Public()),
	}

	b, err := x509.CreateCertificate(rand.Reader, root, root, signer.Public(), signer)

I replaced the resp.PublicKey with signer.Public(). But I'm having a problem, it generates the certificate but when it reads it in this line:

	root, err = pemutil.ReadCertificate("root_ca.crt")
	if err != nil {
		return err
	}

I get this error: x509: provided PrivateKey doesn't match parent's PublicKey

I don't understand what this means, this is a root certificate so of course it doesn't have a parent! Is signer.Public() the wrong public key to use?

hongkongkiwi avatar Nov 16 '21 04:11 hongkongkiwi

Your change look ok, but that error must be from x509.CreateCertificate() not from pemutil.ReadCertificate()

And If you already have an intermediate key, you must do a similar change, few lines below, but taking into account that you will have two signers,

Here's a version changing few names to make it clear


// Get root signer from AWS
rootSigner, err := c.CreateSigner(&apiv1.CreateSignerRequest{
	SigningKey: "awskms:key-id=<root-key-id>",
})
if err != nil {
	return err
}

// Self sign root
now := time.Now()
rootPublicKey := signer.Public()
root := &x509.Certificate{
	IsCA:                  true,
	NotBefore:             now,
	NotAfter:              now.Add(time.Hour * 24 * 365 * 10),
	KeyUsage:              x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
	BasicConstraintsValid: true,
	MaxPathLen:            1,
	MaxPathLenZero:        false,
	Issuer:                pkix.Name{CommonName: "My Root CA (Development)"},
	Subject:               pkix.Name{CommonName: "My Root CA (Development)"},
	SerialNumber:          mustSerialNumber(),
	SubjectKeyId:          mustSubjectKeyID(rootPublicKey),
	AuthorityKeyId:        mustSubjectKeyID(rootPublicKey),
}

b, err := x509.CreateCertificate(rand.Reader, root, root, rootPublicKey, rootSigner)
if err != nil {
	return err
}

// Some extra stuff here ...

root, err = pemutil.ReadCertificate("root_ca.crt")
if err != nil {
	return err
}

// Get intermediate key from AWS Certificate
intermediateSigner, err := c.CreateSigner(&apiv1.CreateSignerRequest{
	SigningKey: "awskms:key-id=<intermediate-key-id>",
})
if err != nil {
	return err
}

// Sign intermediate with root
intermediatePublicKey := intermediateSigner.Public()
intermediate := &x509.Certificate{
	IsCA:                  true,
	NotBefore:             now,
	NotAfter:              now.Add(time.Hour * 24 * 365 * 10),
	KeyUsage:              x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
	BasicConstraintsValid: true,
	MaxPathLen:            0,
	MaxPathLenZero:        true,
	Issuer:                root.Subject,
	Subject:               pkix.Name{CommonName: "My Intermediate CA (Development)"},
	SerialNumber:          mustSerialNumber(),
	SubjectKeyId:          mustSubjectKeyID(intermediatePublicKey),
}

b, err = x509.CreateCertificate(rand.Reader, intermediate, root, intermediatePublicKey, rootSigner)
if err != nil {
	return err
}
...

maraino avatar Nov 17 '21 21:11 maraino