Skip to content

Commit

Permalink
Avoid redundant talk with the contracts server
Browse files Browse the repository at this point in the history
We don't need to querry the contract server if whe have a non-expired,
store-backed Ubuntu Pro token.
  • Loading branch information
EduardGomezEscandell committed Oct 30, 2023
1 parent 7150b63 commit a283521
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 26 deletions.
28 changes: 27 additions & 1 deletion windows-agent/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"path/filepath"
"sync"

"github.com/canonical/ubuntu-pro-for-windows/common"
"github.com/canonical/ubuntu-pro-for-windows/windows-agent/internal/config/registry"
"github.com/canonical/ubuntu-pro-for-windows/windows-agent/internal/contracts"
"github.com/canonical/ubuntu-pro-for-windows/windows-agent/internal/distros/database"
Expand Down Expand Up @@ -219,11 +220,36 @@ func (c *Config) FetchMicrosoftStoreSubscription(ctx context.Context) (err error
return fmt.Errorf("subscription cannot be user-managed")
}

proToken, err := contracts.ProToken(ctx)
_, src, err := c.Subscription(ctx)
if err != nil {
return fmt.Errorf("could not get current subscription status: %v", err)
}

// Shortcut to avoid spamming the contract server
// We don't need to request a new token if we have a non-expired one
if src == SourceMicrosoftStore {
expired, err := contracts.Expired()
if err != nil {
return fmt.Errorf("could not obtain current subscription expiration: %v", err)
}

if !expired {
log.Debug(ctx, "Microsoft Store subscription is active")
return nil
}

log.Debug(ctx, "Microsoft Store subscription is expired")
}

proToken, err := contracts.NewProToken(ctx)
if err != nil {
return fmt.Errorf("could not get ProToken from Microsoft Store: %v", err)
}

if proToken != "" {
log.Debugf(ctx, "Obtained Store-backed pro token: %q", common.Obfuscate(proToken))
}

if err := c.setStoreSubscription(ctx, proToken); err != nil {
return err
}
Expand Down
51 changes: 26 additions & 25 deletions windows-agent/internal/contracts/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"github.com/canonical/ubuntu-pro-for-windows/storeapi/go-wrapper/microsoftstore"
"github.com/canonical/ubuntu-pro-for-windows/windows-agent/internal/contracts/contractclient"
"github.com/ubuntu/decorate"
)

type options struct {
Expand Down Expand Up @@ -52,10 +51,31 @@ func (msftStoreDLL) GetSubscriptionExpirationDate() (tm time.Time, err error) {
return microsoftstore.GetSubscriptionExpirationDate()
}

// ProToken directs the dance between the Microsoft Store and the Ubuntu Pro contract server to
func Expired(args ...Option) (bool, error) {
opts := options{
microsoftStore: msftStoreDLL{},
}

for _, f := range args {
f(&opts)
}

expiration, err := opts.microsoftStore.GetSubscriptionExpirationDate()
if err != nil {
return false, fmt.Errorf("could not get subscription expiration date: %v", err)
}

if expiration.After(time.Now()) {
return false, nil
}

return true, nil
}

// NewProToken directs the dance between the Microsoft Store and the Ubuntu Pro contract server to
// validate a store entitlement and obtain its associated pro token. If there is no entitlement,
// the token is returned as an empty string.
func ProToken(ctx context.Context, args ...Option) (token string, err error) {
func NewProToken(ctx context.Context, args ...Option) (token string, err error) {
opts := options{
microsoftStore: msftStoreDLL{},
}
Expand All @@ -73,28 +93,9 @@ func ProToken(ctx context.Context, args ...Option) (token string, err error) {
}

contractClient := contractclient.New(opts.proURL, &http.Client{Timeout: 30 * time.Second})
msftStore := opts.microsoftStore

token, err = proToken(ctx, contractClient, opts.microsoftStore)
if err != nil {
return "", err
}

return token, nil
}

func proToken(ctx context.Context, serverClient *contractclient.Client, msftStore MicrosoftStore) (proToken string, err error) {
defer decorate.OnError(&err, "could not obtain pro token")

expiration, err := msftStore.GetSubscriptionExpirationDate()
if err != nil {
return "", fmt.Errorf("could not get subscription expiration date: %v", err)
}

if expiration.Before(time.Now()) {
return "", fmt.Errorf("the subscription has been expired since %s", expiration)
}

adToken, err := serverClient.GetServerAccessToken(ctx)
adToken, err := contractClient.GetServerAccessToken(ctx)
if err != nil {
return "", err
}
Expand All @@ -104,7 +105,7 @@ func proToken(ctx context.Context, serverClient *contractclient.Client, msftStor
return "", err
}

proToken, err = serverClient.GetProToken(ctx, storeToken)
proToken, err := contractClient.GetProToken(ctx, storeToken)
if err != nil {
return "", err
}
Expand Down

0 comments on commit a283521

Please sign in to comment.