Skip to content

Commit

Permalink
Expose MSAL PoP for Consistent CSP Integration (#542)
Browse files Browse the repository at this point in the history
* progress

* missing test files

* clean up

* fix popkey

* clean up unnecessary method

* address comments

* cleanup

* add comments

* update nil to explicit function

* cleanup

* cleanup
  • Loading branch information
JorgeDaboub authored Dec 2, 2024
1 parent d3cc69c commit 8d6ce2f
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 23 deletions.
9 changes: 7 additions & 2 deletions pkg/internal/pop/msal_confidential.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ func AcquirePoPTokenConfidential(
clientID,
tenantID string,
options *azcore.ClientOptions,
popKeyFunc func() (*SwKey, error),
) (string, int64, error) {
popKey, err := GetSwPoPKey()
if popKeyFunc == nil {
popKeyFunc = GetSwPoPKey
}
popKey, err := popKeyFunc()
if err != nil {
return "", -1, err
return "", -1, fmt.Errorf("unable to get PoP key: %w", err)
}

authnScheme := &PoPAuthenticationScheme{
Host: popClaims["u"],
PoPKey: popKey,
Expand Down
1 change: 1 addition & 0 deletions pkg/internal/pop/msal_confidential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ func TestAcquirePoPTokenConfidential(t *testing.T) {
tc.p.clientID,
tc.p.tenantID,
&clientOpts,
GetSwPoPKey,
)
defer vcrRecorder.Stop()
if tc.expectedError != nil {
Expand Down
42 changes: 21 additions & 21 deletions pkg/internal/pop/poptoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,46 +27,46 @@ type PoPKey interface {
}

// software based pop key implementation of PoPKey
type swKey struct {
type SwKey struct {
key *rsa.PrivateKey
keyID string
jwk string
jwkTP string
reqCnf string
}

// Alg returns the algorithm used to encrypt/sign the swKey
func (swk *swKey) Alg() string {
// Alg returns the algorithm used to encrypt/sign the SwKey
func (swk *SwKey) Alg() string {
return "RS256"
}

// KeyID returns the keyID of the swKey, representing the key used to sign the swKey
func (swk *swKey) KeyID() string {
// KeyID returns the keyID of the SwKey, representing the key used to sign the SwKey
func (swk *SwKey) KeyID() string {
return swk.keyID
}

// JWK returns the JSON Web Key of the given swKey
func (swk *swKey) JWK() string {
// JWK returns the JSON Web Key of the given SwKey
func (swk *SwKey) JWK() string {
return swk.jwk
}

// JWKThumbprint returns the JWK thumbprint of the given swKey
func (swk *swKey) JWKThumbprint() string {
// JWKThumbprint returns the JWK thumbprint of the given SwKey
func (swk *SwKey) JWKThumbprint() string {
return swk.jwkTP
}

// ReqCnf returns the req_cnf claim to send to AAD for the given swKey
func (swk *swKey) ReqCnf() string {
// ReqCnf returns the req_cnf claim to send to AAD for the given SwKey
func (swk *SwKey) ReqCnf() string {
return swk.reqCnf
}

// Sign uses the given swKey to sign the given payload and returns the signed payload
func (swk *swKey) Sign(payload []byte) ([]byte, error) {
// Sign uses the given SwKey to sign the given payload and returns the signed payload
func (swk *SwKey) Sign(payload []byte) ([]byte, error) {
return swk.key.Sign(rand.Reader, payload, crypto.SHA256)
}

// init initializes the given swKey using the given private key
func (swk *swKey) init(key *rsa.PrivateKey) {
// init initializes the given SwKey using the given private key
func (swk *SwKey) init(key *rsa.PrivateKey) {
swk.key = key

eB64, nB64 := getRSAKeyExponentAndModulus(key)
Expand All @@ -81,23 +81,23 @@ func (swk *swKey) init(key *rsa.PrivateKey) {
swk.jwk = getJWK(eB64, nB64, swk.keyID)
}

// generateSwKey generates a new swkey and initializes it with required fields before returning it
func generateSwKey(key *rsa.PrivateKey) (*swKey, error) {
swk := &swKey{}
// generateSwKey generates a new SwKey and initializes it with required fields before returning it
func generateSwKey(key *rsa.PrivateKey) (*SwKey, error) {
swk := &SwKey{}
swk.init(key)
return swk, nil
}

// GetSwPoPKey generates a new PoP key that rotates every 8 hours and returns it
func GetSwPoPKey() (*swKey, error) {
// GetSwPoPKey generates a new PoP key returns it
func GetSwPoPKey() (*SwKey, error) {
key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, fmt.Errorf("error generating RSA private key: %w", err)
}
return GetSwPoPKeyWithRSAKey(key)
}

func GetSwPoPKeyWithRSAKey(rsaKey *rsa.PrivateKey) (*swKey, error) {
func GetSwPoPKeyWithRSAKey(rsaKey *rsa.PrivateKey) (*SwKey, error) {
key, err := generateSwKey(rsaKey)
if err != nil {
return nil, fmt.Errorf("unable to generate PoP key. err: %w", err)
Expand Down
1 change: 1 addition & 0 deletions pkg/internal/token/serviceprincipaltokencertificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func (p *servicePrincipalToken) getPoPTokenWithClientCert(
p.clientID,
p.tenantID,
options,
pop.GetSwPoPKey,
)
if err != nil {
return "", -1, fmt.Errorf("failed to create service principal PoP token using certificate: %w", err)
Expand Down
1 change: 1 addition & 0 deletions pkg/internal/token/serviceprincipaltokensecret.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func (p *servicePrincipalToken) getPoPTokenWithClientSecret(
p.clientID,
p.tenantID,
options,
pop.GetSwPoPKey,
)
if err != nil {
return "", -1, fmt.Errorf("failed to create service principal PoP token using secret: %w", err)
Expand Down
9 changes: 9 additions & 0 deletions pkg/pop/msal_confidential.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package pop

import (
"github.com/Azure/kubelogin/pkg/internal/pop"
)

// AcquirePoPTokenConfidential retrieves a Proof of Possession (PoP) token using confidential client credentials.
// It utilizes the internal pop.AcquirePoPTokenConfidential function to obtain the token.
var AcquirePoPTokenConfidential = pop.AcquirePoPTokenConfidential
7 changes: 7 additions & 0 deletions pkg/pop/poptoken.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package pop

import "github.com/Azure/kubelogin/pkg/internal/pop"

// GetSwPoPKey retrieves a software Proof of Possession (PoP) key using RSA encryption.
// It utilizes the internal pop.GetSwPoPKey function to obtain the key.
var GetSwPoPKey = pop.GetSwPoPKey
12 changes: 12 additions & 0 deletions pkg/pop/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package pop

import (
"github.com/Azure/kubelogin/pkg/internal/pop"
)

// This is the MSAL implementation of AuthenticationScheme.
// For more details, see the MSAL repo interface:
// https://github.com/AzureAD/microsoft-authentication-library-for-go/blob/4a4dafcbcbd7d57a69ed3bc59760381232c2be9c/apps/internal/oauth/ops/authority/authority.go#L146
type PoPAuthenticationScheme = pop.PoPAuthenticationScheme

type SwKey = pop.SwKey

0 comments on commit 8d6ce2f

Please sign in to comment.