Skip to content

Commit

Permalink
Merge pull request #30 from rickardgranberg/dev/fix_dns
Browse files Browse the repository at this point in the history
Attempt at fixing DNS resolution error during login
  • Loading branch information
rickardgranberg authored Oct 1, 2021
2 parents a87a836 + 3800542 commit 3521619
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
uses: crazy-max/ghaction-import-gpg@v4
with:
# These secrets will need to be configured for the repository:
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PASSPHRASE }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
Expand Down
11 changes: 8 additions & 3 deletions cmd/patissuer/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func Execute(version, commit, buildTime string) error {
}

func issue(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(viper.GetInt(flagLoginRetry))*time.Minute)
defer cancel()

cl, err := loginAndCreateClient(ctx)
Expand Down Expand Up @@ -91,7 +91,7 @@ func issue(cmd *cobra.Command, args []string) error {
}

func list(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(viper.GetInt(flagLoginRetry))*time.Minute)
defer cancel()

cl, err := loginAndCreateClient(ctx)
Expand Down Expand Up @@ -134,7 +134,12 @@ func loginAndCreateClient(ctx context.Context) (*devops.Client, error) {
var t string

for i := 0; i < viper.GetInt(flagLoginRetry); i++ {
t, err = authClient.Login(ctx, viper.GetString(flagLoginMethod), viper.GetString(flagLoginToken))
sctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
t, err = authClient.Login(sctx, viper.GetString(flagLoginMethod), viper.GetString(flagLoginToken))
if err == context.Canceled {
return nil, fmt.Errorf("login canceled %w", err)
}
if err != nil {
log.Printf("failed to login with error: %v\n", err)
log.Printf("Retrying login (%d of %d)...", i+1, viper.GetInt(flagLoginRetry))
Expand Down
33 changes: 26 additions & 7 deletions pkg/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package auth
import (
"context"
"fmt"
"net"
"net/http"

"github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
)
Expand All @@ -19,7 +21,8 @@ const (
LoginMethodBearerToken = "bearertoken"
)

const aadInstance = "https://login.microsoftonline.com/%s/v2.0"
const loginHost = "login.microsoftonline.com"
const aadInstance = "https://" + loginHost + "/%s/v2.0"

var scopes = []string{"499b84ac-1321-427f-aa17-267ca6975798/user_impersonation"} //Constant value to target Azure DevOps. Do not change

Expand All @@ -29,11 +32,13 @@ func NewAuthClient(tenantId, clientId string) (*AuthClient, error) {
clientId: clientId,
}

http := &http.Client{}
client, err := public.New(clientId,
public.WithHTTPClient(http),
public.WithAuthority(fmt.Sprintf(aadInstance, tenantId)))

if err != nil {
return nil, err
return nil, fmt.Errorf("error creating client: %w", err)
}

cl.client = client
Expand Down Expand Up @@ -63,26 +68,40 @@ func (a *AuthClient) loginBearerToken(ctx context.Context, token string) (string
}

func (a *AuthClient) loginInteractive(ctx context.Context) (string, error) {
// This is done as an attempt to avoid DNS resolution errors during login:
_, err := net.LookupHost(loginHost)

if err != nil {
return "", fmt.Errorf("name lookup error: %w", err)
}

accounts := a.client.Accounts()
if len(accounts) > 0 {
// Assuming the user wanted the first account
userAccount := accounts[0]
// found a cached account, now see if an applicable token has been cached
result, err := a.client.AcquireTokenSilent(ctx, scopes, public.WithSilentAccount(userAccount))
if err != nil {
return "", err
return "", fmt.Errorf("aquire token silent failed: %w", err)
}
return result.AccessToken, nil
}

result, err := a.client.AcquireTokenInteractive(ctx, scopes, public.WithRedirectURI("http://localhost"))
if err != nil {
return "", err
return "", fmt.Errorf("aquire token interactive failed: %w", err)
}
return result.AccessToken, nil
}

func (a *AuthClient) loginDeviceCode(ctx context.Context) (string, error) {
// This is done as an attempt to avoid DNS resolution errors during login:
_, err := net.LookupHost(loginHost)

if err != nil {
return "", fmt.Errorf("name lookup error: %w", err)
}

accounts := a.client.Accounts()
if len(accounts) > 0 {
// Assuming the user wanted the first account
Expand All @@ -92,18 +111,18 @@ func (a *AuthClient) loginDeviceCode(ctx context.Context) (string, error) {
if err != nil {
return "", err
}
return result.AccessToken, nil
return result.AccessToken, fmt.Errorf("aquire token silent failed: %w", err)
}

code, err := a.client.AcquireTokenByDeviceCode(ctx, scopes)
if err != nil {
return "", err
return "", fmt.Errorf("aquire token device code failed: %w", err)
}

fmt.Println(code.Result.Message)
result, err := code.AuthenticationResult(ctx)
if err != nil {
return "", err
return "", fmt.Errorf("auth result failed: %w", err)
}
return result.AccessToken, nil
}

0 comments on commit 3521619

Please sign in to comment.