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

Update CF URLSigner to use crypto.Signer interface #2087

Merged
merged 1 commit into from
Apr 11, 2023
Merged

Conversation

rem7
Copy link
Contributor

@rem7 rem7 commented Apr 7, 2023

This is a proposal to update CloudFront's URLSigner to use the crypto.Signer interface.

URLSigner takes a *rsa.PrivateKey as an input to sign the pre-signed URL. If we update the function to receive the crypto.Signer interface (already implemented by rsa.PrivateKey) it allows us to use other keys to sign cloudfront URLs. For example hardware keys. This change is also more Go idiomatic.

Here is a working example of generating a pre-signed URL with a PIV key stored in a Yubikey:

package main

import (
	"crypto"
	"fmt"
	"github.com/aws/aws-sdk-go-v2/feature/cloudfront/sign"
	"github.com/go-piv/piv-go/piv"
	"log"
	"strings"
	"time"
)

func main() {

	urlstr := "https://cdn.mydomain.com/images/image1.jpg"

	var privKey crypto.Signer
	var keyID string
	keyID, privKey = getPrivateKeyFromHardware()

	signer := sign.NewURLSigner(keyID, privKey)
	signedURL, err := signer.Sign(urlstr, time.Now().Add(1*time.Minute))
	if err != nil {
		log.Fatalf("Failed to sign url, err: %s\n", err.Error())
	}
	fmt.Printf("%s\n", signedURL)

}

func getPrivateKeyFromHardware() (string, crypto.Signer) {

	keyID := "XXXXXXXXXXXX"
	fmt.Printf("getting hardware keys\n")
	cards, err := piv.Cards()
	if err != nil {
		panic(err)
	}

	var yk *piv.YubiKey
	for _, card := range cards {
		fmt.Printf("%+v\n", card)
		if strings.Contains(strings.ToLower(card), "yubikey") {
			if yk, err = piv.Open(card); err != nil {
				panic(err)
			}
			break
		}
	}

	auth := piv.KeyAuth{PIN: piv.DefaultPIN}
	cert, err := yk.Attest(piv.SlotAuthentication)
	if err != nil {
		log.Fatalf(err.Error())
	}
	priv, err := yk.PrivateKey(piv.SlotAuthentication, cert.PublicKey, auth)
	if err != nil {
		log.Fatalf(err.Error())
	}

	p, ok := priv.(crypto.Signer)
	if !ok {
		log.Fatalf("unable to cast")
	}

	return keyID, p
}

It shouldn't break compatibility with previous usage since *rsa.PrivateKey already implements crypto.Signer


For changes to files under the /codegen/aws-models folder, and manual edits to autogenerated code (e.g. /service/s3/api.go) please create an Issue instead of a PR for those type of changes.

If the PR addresses an existing bug or feature, please reference it here.

To help speed up the process and reduce the time to merge please ensure that Allow edits by maintainers is checked before submitting your PR. This will allow the project maintainers to make minor adjustments or improvements to the submitted PR, allow us to reduce the roundtrip time for merging your request.

CloudFront URLSigner uses *rsa.PrivateKey to sign the URL. If we update
the function to receive the crypto.Signer interface (already implemented
by rsa.PrivateKey) then we can use other keys to sign. For example
hardware keys.
@rem7 rem7 requested a review from a team as a code owner April 7, 2023 17:43
Copy link
Contributor

@aajtodd aajtodd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR

@aajtodd aajtodd merged commit a340c5c into aws:main Apr 11, 2023
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants