From 2491593cdd0bb71e2133461b857cddfc99cd0950 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 6 Jun 2019 12:49:51 -0700 Subject: [PATCH] Add ca-url based audience for AWS tokens Fixes smallstep/step#156 --- authority/provisioner/aws.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/authority/provisioner/aws.go b/authority/provisioner/aws.go index 29d937e9..33c35fe0 100644 --- a/authority/provisioner/aws.go +++ b/authority/provisioner/aws.go @@ -131,11 +131,12 @@ type AWS struct { Claims *Claims `json:"claims,omitempty"` claimer *Claimer config *awsConfig + audiences Audiences } // GetID returns the provisioner unique identifier. func (p *AWS) GetID() string { - return "aws:" + p.Name + return "aws/" + p.Name } // GetTokenID returns the identifier of the token. @@ -170,7 +171,7 @@ func (p *AWS) GetEncryptedKey() (kid string, key string, ok bool) { // GetIdentityToken retrieves the identity document and it's signature and // generates a token with them. -func (p *AWS) GetIdentityToken() (string, error) { +func (p *AWS) GetIdentityToken(caURL string) (string, error) { // Initialize the config if this method is used from the cli. if err := p.assertConfig(); err != nil { return "", err @@ -196,6 +197,11 @@ func (p *AWS) GetIdentityToken() (string, error) { return "", err } + audience, err := generateSignAudience(caURL, p.GetID()) + if err != nil { + return "", err + } + // Create unique ID for Trust On First Use (TOFU). Only the first instance // per provisioner is allowed as we don't have a way to trust the given // sans. @@ -216,7 +222,7 @@ func (p *AWS) GetIdentityToken() (string, error) { Claims: jose.Claims{ Issuer: awsIssuer, Subject: idoc.InstanceID, - Audience: []string{p.GetID()}, + Audience: []string{audience}, Expiry: jose.NewNumericDate(now.Add(5 * time.Minute)), NotBefore: jose.NewNumericDate(now), IssuedAt: jose.NewNumericDate(now), @@ -254,6 +260,7 @@ func (p *AWS) Init(config Config) (err error) { if p.config, err = newAWSConfig(); err != nil { return err } + p.audiences = config.Audiences.WithFragment(p.GetID()) return nil } @@ -381,14 +388,18 @@ func (p *AWS) authorizeToken(token string) (*awsPayload, error) { // more than a few minutes. now := time.Now().UTC() if err = payload.ValidateWithLeeway(jose.Expected{ - Issuer: awsIssuer, - Subject: doc.InstanceID, - Audience: []string{p.GetID()}, - Time: now, + Issuer: awsIssuer, + Subject: doc.InstanceID, + Time: now, }, time.Minute); err != nil { return nil, errors.Wrapf(err, "invalid token") } + // validate audiences with the defaults + if !matchesAudience(payload.Audience, p.audiences.Sign) { + return nil, errors.New("invalid token: invalid audience claim (aud)") + } + // validate accounts if len(p.Accounts) > 0 { var found bool