From e77e9ddd8767ee097a1e2d883d277b4e8662ac92 Mon Sep 17 00:00:00 2001 From: Gerd Oberlechner Date: Fri, 31 Jan 2025 20:28:56 +0100 Subject: [PATCH 1/3] refresh GH action ID token during pipeline runs mitigation for https://github.com/Azure/azure-cli/issues/28708 Signed-off-by: Gerd Oberlechner --- .github/workflows/services-pr-check.yml | 31 ++--- tooling/templatize/cmd/pipeline/run/cmd.go | 6 + tooling/templatize/internal/end2end/e2e.go | 4 +- .../templatize/internal/end2end/e2e_test.go | 8 +- tooling/templatize/pkg/aks/admin.go | 7 +- tooling/templatize/pkg/aks/kubeconfig.go | 5 +- tooling/templatize/pkg/azauth/auth.go | 37 ++++++ tooling/templatize/pkg/azauth/github.go | 117 ++++++++++++++++++ tooling/templatize/pkg/pipeline/arm.go | 4 +- .../pkg/pipeline/executiontarget.go | 4 +- 10 files changed, 194 insertions(+), 29 deletions(-) create mode 100644 tooling/templatize/pkg/azauth/auth.go create mode 100644 tooling/templatize/pkg/azauth/github.go diff --git a/.github/workflows/services-pr-check.yml b/.github/workflows/services-pr-check.yml index bd7bb223b..23a8fb890 100644 --- a/.github/workflows/services-pr-check.yml +++ b/.github/workflows/services-pr-check.yml @@ -3,6 +3,11 @@ env: DEPLOY_ENV: dev SKIP_CONFIRM: true + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ + PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} on: pull_request: paths: @@ -33,8 +38,6 @@ jobs: service_cluster_pr_check: - env: - PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} permissions: id-token: 'write' contents: 'read' @@ -47,12 +50,12 @@ - name: "install azure-cli" uses: "Azure/ARO-HCP@main" - - name: 'Az CLI login' - uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 - with: - client-id: ${{ secrets.AZURE_CLIENT_ID }} - tenant-id: ${{ secrets.AZURE_TENANT_ID }} - subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + # - name: 'Az CLI login' + # uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 + # with: + # client-id: ${{ secrets.AZURE_CLIENT_ID }} + # tenant-id: ${{ secrets.AZURE_TENANT_ID }} + # subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - uses: azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f # v4.0.0 @@ -119,12 +122,12 @@ - name: "install azure-cli" uses: "Azure/ARO-HCP@main" - - name: 'Az CLI login' - uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 - with: - client-id: ${{ secrets.AZURE_CLIENT_ID }} - tenant-id: ${{ secrets.AZURE_TENANT_ID }} - subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + # - name: 'Az CLI login' + # uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 + # with: + # client-id: ${{ secrets.AZURE_CLIENT_ID }} + # tenant-id: ${{ secrets.AZURE_TENANT_ID }} + # subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - uses: azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f # v4.0.0 diff --git a/tooling/templatize/cmd/pipeline/run/cmd.go b/tooling/templatize/cmd/pipeline/run/cmd.go index afd5f63a7..57b0b3adc 100644 --- a/tooling/templatize/cmd/pipeline/run/cmd.go +++ b/tooling/templatize/cmd/pipeline/run/cmd.go @@ -4,6 +4,8 @@ import ( "context" "github.com/spf13/cobra" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/azauth" ) func NewCommand() (*cobra.Command, error) { @@ -31,5 +33,9 @@ func runPipeline(ctx context.Context, opts *RawRunOptions) error { if err != nil { return err } + err = azauth.SetupAzureAuth(ctx) + if err != nil { + return err + } return completed.RunPipeline(ctx) } diff --git a/tooling/templatize/internal/end2end/e2e.go b/tooling/templatize/internal/end2end/e2e.go index c9a76cfe4..4b66d8ef1 100644 --- a/tooling/templatize/internal/end2end/e2e.go +++ b/tooling/templatize/internal/end2end/e2e.go @@ -9,9 +9,9 @@ import ( "gopkg.in/yaml.v2" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/azauth" "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" ) @@ -112,7 +112,7 @@ func (e *e2eImpl) UseRandomRG() func() error { if err != nil { return err } - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azauth.GetAzureTokenCredentials() if err != nil { return err } diff --git a/tooling/templatize/internal/end2end/e2e_test.go b/tooling/templatize/internal/end2end/e2e_test.go index 94366e5da..bb0f91ae3 100644 --- a/tooling/templatize/internal/end2end/e2e_test.go +++ b/tooling/templatize/internal/end2end/e2e_test.go @@ -10,10 +10,10 @@ import ( "gotest.tools/v3/assert" "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline/run" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/azauth" "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" ) @@ -107,7 +107,7 @@ param zoneName = 'e2etestarmdeploy.foo.bar.example.com' subsriptionID, err := pipeline.LookupSubscriptionID(context.Background(), "ARO Hosted Control Planes (EA Subscription 1)") assert.NilError(t, err) - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azauth.GetAzureTokenCredentials() assert.NilError(t, err) zonesClient, err := armdns.NewZonesClient(subsriptionID, cred, nil) @@ -314,7 +314,7 @@ resource newRG 'Microsoft.Resources/resourceGroups@2024-03-01' = { subsriptionID, err := pipeline.LookupSubscriptionID(context.Background(), "ARO Hosted Control Planes (EA Subscription 1)") assert.NilError(t, err) - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azauth.GetAzureTokenCredentials() assert.NilError(t, err) rgClient, err := armresources.NewResourceGroupsClient(subsriptionID, cred, nil) @@ -354,7 +354,7 @@ param zoneName = 'e2etestarmdeploy.foo.bar.example.com' subsriptionID, err := pipeline.LookupSubscriptionID(context.Background(), "ARO Hosted Control Planes (EA Subscription 1)") assert.NilError(t, err) - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azauth.GetAzureTokenCredentials() assert.NilError(t, err) zonesClient, err := armdns.NewZonesClient(subsriptionID, cred, nil) diff --git a/tooling/templatize/pkg/aks/admin.go b/tooling/templatize/pkg/aks/admin.go index 3e8700f00..57983990f 100644 --- a/tooling/templatize/pkg/aks/admin.go +++ b/tooling/templatize/pkg/aks/admin.go @@ -9,7 +9,6 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" armauthorization "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3" "github.com/google/uuid" auth "github.com/microsoft/kiota-authentication-azure-go" @@ -17,6 +16,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/azauth" ) const ( @@ -99,7 +100,7 @@ func getCurrentUserObjectID(ctx context.Context) (string, error) { } // Create a Graph client using Azure Credentials - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azauth.GetAzureTokenCredentials() if err != nil { return "", fmt.Errorf("failed to obtain a credential: %w", err) } @@ -130,7 +131,7 @@ func getCurrentUserObjectID(ctx context.Context) (string, error) { func assignClusterAdminRBACRole(ctx context.Context, subscriptionID, resourceGroupName, aksClusterName, userObjectID, roleID string) error { // Create a new Azure identity client - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azauth.GetAzureTokenCredentials() if err != nil { return fmt.Errorf("failed to obtain a credential: %w", err) } diff --git a/tooling/templatize/pkg/aks/kubeconfig.go b/tooling/templatize/pkg/aks/kubeconfig.go index 3baf53503..096aded5c 100644 --- a/tooling/templatize/pkg/aks/kubeconfig.go +++ b/tooling/templatize/pkg/aks/kubeconfig.go @@ -6,8 +6,9 @@ import ( "os" "os/exec" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/azauth" ) func GetKubeConfig(ctx context.Context, subscriptionID, resourceGroupName, aksClusterName string) (string, error) { @@ -16,7 +17,7 @@ func GetKubeConfig(ctx context.Context, subscriptionID, resourceGroupName, aksCl } // Create a new Azure identity client - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azauth.GetAzureTokenCredentials() if err != nil { return "", fmt.Errorf("failed to obtain a credential: %v", err) } diff --git a/tooling/templatize/pkg/azauth/auth.go b/tooling/templatize/pkg/azauth/auth.go new file mode 100644 index 000000000..bc302ce48 --- /dev/null +++ b/tooling/templatize/pkg/azauth/auth.go @@ -0,0 +1,37 @@ +package azauth + +import ( + "context" + "fmt" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" +) + +func SetupAzureAuth(ctx context.Context) error { + if githubAuthSupported() { + err := setupGithubAzureFederationAuthRefresher(ctx) + if err != nil { + return fmt.Errorf("failed to setup GitHub Azure Federation Auth Refresher: %w", err) + } + } + return nil +} + +func GetAzureTokenCredentials() (azcore.TokenCredential, error) { + azCLI, err := azidentity.NewAzureCLICredential(nil) + if err != nil { + return nil, err + } + + def, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return nil, err + } + + chain, err := azidentity.NewChainedTokenCredential([]azcore.TokenCredential{azCLI, def}, nil) + if err != nil { + return nil, err + } + return chain, nil +} diff --git a/tooling/templatize/pkg/azauth/github.go b/tooling/templatize/pkg/azauth/github.go new file mode 100644 index 000000000..5600cff07 --- /dev/null +++ b/tooling/templatize/pkg/azauth/github.go @@ -0,0 +1,117 @@ +package azauth + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "os/exec" + "time" + + "github.com/go-logr/logr" +) + +const ( + AZURE_CLIENT_ID = "AZURE_CLIENT_ID" + AZURE_TENANT_ID = "AZURE_TENANT_ID" + AZURE_FEDERATED_TOKEN_FILE = "AZURE_FEDERATED_TOKEN_FILE" + ACTIONS_ID_TOKEN_REQUEST_URL = "ACTIONS_ID_TOKEN_REQUEST_URL" + ACTIONS_ID_TOKEN_REQUEST_TOKEN = "ACTIONS_ID_TOKEN_REQUEST_TOKEN" +) + +func githubAuthSupported() bool { + if _, ok := os.LookupEnv(AZURE_CLIENT_ID); !ok { + return false + } + if _, ok := os.LookupEnv(AZURE_TENANT_ID); !ok { + return false + } + if _, ok := os.LookupEnv(ACTIONS_ID_TOKEN_REQUEST_URL); !ok { + return false + } + if _, ok := os.LookupEnv(ACTIONS_ID_TOKEN_REQUEST_TOKEN); !ok { + return false + } + return true +} + +func setupGithubAzureFederationAuthRefresher(ctx context.Context) error { + logger := logr.FromContextOrDiscard(ctx) + clientId := os.Getenv(AZURE_CLIENT_ID) + tenantId := os.Getenv(AZURE_TENANT_ID) + requestToken := os.Getenv(ACTIONS_ID_TOKEN_REQUEST_TOKEN) + requestURL := os.Getenv(ACTIONS_ID_TOKEN_REQUEST_URL) + err := refreshGithubAzureFederatedSession(ctx, clientId, tenantId, requestURL, requestToken) + if err != nil { + return fmt.Errorf("failed to refresh Azure session with federated GitHub ID token: %w", err) + } + go func() { + ticker := time.NewTicker(5 * time.Minute) + defer ticker.Stop() + for { + select { + case <-ticker.C: + err := refreshGithubAzureFederatedSession(ctx, clientId, tenantId, requestURL, requestToken) + if err != nil { + logger.Error(err, "failed to refresh Azure session with federated GitHub ID token") + } + case <-ctx.Done(): + return + } + } + }() + return nil +} + +func refreshGithubAzureFederatedSession(ctx context.Context, clientId, tenantId, requestUrl, requestToken string) error { + logger := logr.FromContextOrDiscard(ctx) + logger.V(7).Info("Refreshing Azure session with federated GitHub ID token") + token, err := getGithubIDToken(requestUrl, requestToken) + if err != nil { + return fmt.Errorf("failed to get GitHub ID token: %w", err) + } + cmd := exec.CommandContext(ctx, "az", "login", "--service-principal", "--username", clientId, "--tenant", tenantId, "--federated-token", token) + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("failed to run az login: %s %v", string(output), err) + } + logger.V(7).Info("Azure session refreshed with federated GitHub ID token", "az cli output", output) + return nil +} + +func getGithubIDToken(requestURL, requestToken string) (string, error) { + req, err := http.NewRequest("GET", requestURL, nil) + if err != nil { + return "", fmt.Errorf("failed to create request: %w", err) + } + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", requestToken)) + q := req.URL.Query() + q.Add("audience", "api://AzureADTokenExchange") + req.URL.RawQuery = q.Encode() + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return "", fmt.Errorf("failed to get ID token: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("failed to get ID token: status code %d", resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", fmt.Errorf("failed to read response body: %w", err) + } + + var tokenResponse struct { + Value string `json:"value"` + } + if err := json.Unmarshal(body, &tokenResponse); err != nil { + return "", fmt.Errorf("failed to unmarshal response body: %w", err) + } + + return tokenResponse.Value, nil +} diff --git a/tooling/templatize/pkg/pipeline/arm.go b/tooling/templatize/pkg/pipeline/arm.go index b0637a074..4cf84da90 100644 --- a/tooling/templatize/pkg/pipeline/arm.go +++ b/tooling/templatize/pkg/pipeline/arm.go @@ -6,11 +6,11 @@ import ( "strings" "time" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/azauth" "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" "github.com/go-logr/logr" ) @@ -25,7 +25,7 @@ type armClient struct { } func newArmClient(subscriptionID, region string) *armClient { - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azauth.GetAzureTokenCredentials() if err != nil { return nil } diff --git a/tooling/templatize/pkg/pipeline/executiontarget.go b/tooling/templatize/pkg/pipeline/executiontarget.go index 7964e0bce..76c46ed8c 100644 --- a/tooling/templatize/pkg/pipeline/executiontarget.go +++ b/tooling/templatize/pkg/pipeline/executiontarget.go @@ -4,15 +4,15 @@ import ( "context" "fmt" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions" "github.com/Azure/ARO-HCP/tooling/templatize/pkg/aks" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/azauth" ) func LookupSubscriptionID(ctx context.Context, subscriptionName string) (string, error) { // Create a new Azure identity client - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azauth.GetAzureTokenCredentials() if err != nil { return "", fmt.Errorf("failed to obtain a credential: %v", err) } From 912dfa0b67d67d76f0d0330c88f9a422a67abf4b Mon Sep 17 00:00:00 2001 From: Gerd Oberlechner Date: Mon, 3 Feb 2025 11:02:53 +0100 Subject: [PATCH 2/3] provide env vars to gh actions Signed-off-by: Gerd Oberlechner --- .github/workflows/aro-hcp-cd.yml | 5 +++++ .github/workflows/environment-infra-cd.yml | 12 +++++------- .github/workflows/services-cd.yml | 9 +++++---- .github/workflows/services-ci.yml | 5 +++++ .github/workflows/services-pr-check.yml | 18 +----------------- 5 files changed, 21 insertions(+), 28 deletions(-) diff --git a/.github/workflows/aro-hcp-cd.yml b/.github/workflows/aro-hcp-cd.yml index 7508a31d6..4ab8e1677 100644 --- a/.github/workflows/aro-hcp-cd.yml +++ b/.github/workflows/aro-hcp-cd.yml @@ -4,6 +4,11 @@ DEPLOY_ENV: dev PERSIST: true SKIP_CONFIRM: true + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + #AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ + PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} on: workflow_dispatch: pull_request: diff --git a/.github/workflows/environment-infra-cd.yml b/.github/workflows/environment-infra-cd.yml index e1238a9a9..aa9925233 100644 --- a/.github/workflows/environment-infra-cd.yml +++ b/.github/workflows/environment-infra-cd.yml @@ -4,6 +4,11 @@ DEPLOY_ENV: ${{ inputs.deploy_env }} SKIP_CONFIRM: true PERSIST: true + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + #AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ + PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} on: workflow_call: inputs: @@ -90,12 +95,8 @@ - name: 'Deploy Cluster' run: | cd dev-infrastructure/ - az account get-access-token --output none PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make svc - # grant GH action user access to resources - # PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make svc.dev-role-assignments - - name: 'Az CLI login again' uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 with: @@ -106,7 +107,6 @@ - name: 'Deploy rest' run: | cd dev-infrastructure/ - az account get-access-token --output none PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make svc.aks.admin-access - name: 'CS PR check MSI' @@ -154,7 +154,6 @@ - name: 'Deploy or Update' run: | cd dev-infrastructure/ - az account get-access-token --output none PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make mgmt - name: 'Az CLI login again' @@ -167,5 +166,4 @@ - name: 'Deploy rest' run: | cd dev-infrastructure/ - az account get-access-token --output none PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make mgmt.aks.admin-access diff --git a/.github/workflows/services-cd.yml b/.github/workflows/services-cd.yml index b3aaa7342..961a893ad 100644 --- a/.github/workflows/services-cd.yml +++ b/.github/workflows/services-cd.yml @@ -3,6 +3,11 @@ env: DEPLOY_ENV: ${{ inputs.deploy_env }} SKIP_CONFIRM: true + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + #AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ + PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} on: workflow_call: inputs: @@ -33,8 +38,6 @@ jobs: deploy_to_service_cluster: - env: - PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} permissions: id-token: 'write' contents: 'read' @@ -112,8 +115,6 @@ ./svc-deploy.sh ${DEPLOY_ENV} cluster-service svc deploy-pr-env-deps deploy_to_management_cluster: - env: - PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} permissions: id-token: 'write' contents: 'read' diff --git a/.github/workflows/services-ci.yml b/.github/workflows/services-ci.yml index 6ffece37c..70b302512 100644 --- a/.github/workflows/services-ci.yml +++ b/.github/workflows/services-ci.yml @@ -2,6 +2,11 @@ name: ARO HCP Dev Environment Continuous Deployment env: DEPLOY_ENV: dev + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + #AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ + PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} on: workflow_call: inputs: diff --git a/.github/workflows/services-pr-check.yml b/.github/workflows/services-pr-check.yml index 23a8fb890..2e951d093 100644 --- a/.github/workflows/services-pr-check.yml +++ b/.github/workflows/services-pr-check.yml @@ -6,7 +6,7 @@ AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ + #AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} on: pull_request: @@ -50,13 +50,6 @@ - name: "install azure-cli" uses: "Azure/ARO-HCP@main" - # - name: 'Az CLI login' - # uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 - # with: - # client-id: ${{ secrets.AZURE_CLIENT_ID }} - # tenant-id: ${{ secrets.AZURE_TENANT_ID }} - # subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - - uses: azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f # v4.0.0 # Used to deploy Cluster Service @@ -108,8 +101,6 @@ make metrics.dry_run mgmt_cluster_pr_check: - env: - PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} permissions: id-token: 'write' contents: 'read' @@ -122,13 +113,6 @@ - name: "install azure-cli" uses: "Azure/ARO-HCP@main" - # - name: 'Az CLI login' - # uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 - # with: - # client-id: ${{ secrets.AZURE_CLIENT_ID }} - # tenant-id: ${{ secrets.AZURE_TENANT_ID }} - # subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - - uses: azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f # v4.0.0 # Used to deploy Cluster Service From aede4d20c89fd5b4a4d751a172aad17ed7c5066a Mon Sep 17 00:00:00 2001 From: Gerd Oberlechner Date: Mon, 3 Feb 2025 11:18:08 +0100 Subject: [PATCH 3/3] timeout handling Signed-off-by: Gerd Oberlechner --- tooling/templatize/pkg/azauth/auth.go | 6 +++--- tooling/templatize/pkg/azauth/github.go | 15 ++++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/tooling/templatize/pkg/azauth/auth.go b/tooling/templatize/pkg/azauth/auth.go index bc302ce48..299671d85 100644 --- a/tooling/templatize/pkg/azauth/auth.go +++ b/tooling/templatize/pkg/azauth/auth.go @@ -11,9 +11,9 @@ import ( func SetupAzureAuth(ctx context.Context) error { if githubAuthSupported() { err := setupGithubAzureFederationAuthRefresher(ctx) - if err != nil { - return fmt.Errorf("failed to setup GitHub Azure Federation Auth Refresher: %w", err) - } + if err != nil { + return fmt.Errorf("failed to setup GitHub Azure Federation Auth Refresher: %w", err) + } } return nil } diff --git a/tooling/templatize/pkg/azauth/github.go b/tooling/templatize/pkg/azauth/github.go index 5600cff07..c3dc118e7 100644 --- a/tooling/templatize/pkg/azauth/github.go +++ b/tooling/templatize/pkg/azauth/github.go @@ -68,7 +68,7 @@ func setupGithubAzureFederationAuthRefresher(ctx context.Context) error { func refreshGithubAzureFederatedSession(ctx context.Context, clientId, tenantId, requestUrl, requestToken string) error { logger := logr.FromContextOrDiscard(ctx) logger.V(7).Info("Refreshing Azure session with federated GitHub ID token") - token, err := getGithubIDToken(requestUrl, requestToken) + token, err := getGithubIDToken(ctx, requestUrl, requestToken) if err != nil { return fmt.Errorf("failed to get GitHub ID token: %w", err) } @@ -81,7 +81,11 @@ func refreshGithubAzureFederatedSession(ctx context.Context, clientId, tenantId, return nil } -func getGithubIDToken(requestURL, requestToken string) (string, error) { +func getGithubIDToken(ctx context.Context, requestURL, requestToken string) (string, error) { + timeoutContext, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + + // build request, add auth and audience req, err := http.NewRequest("GET", requestURL, nil) if err != nil { return "", fmt.Errorf("failed to create request: %w", err) @@ -90,22 +94,23 @@ func getGithubIDToken(requestURL, requestToken string) (string, error) { q := req.URL.Query() q.Add("audience", "api://AzureADTokenExchange") req.URL.RawQuery = q.Encode() + + // send request with timeout client := &http.Client{} - resp, err := client.Do(req) + resp, err := client.Do(req.WithContext(timeoutContext)) if err != nil { return "", fmt.Errorf("failed to get ID token: %w", err) } defer resp.Body.Close() + // process response if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("failed to get ID token: status code %d", resp.StatusCode) } - body, err := io.ReadAll(resp.Body) if err != nil { return "", fmt.Errorf("failed to read response body: %w", err) } - var tokenResponse struct { Value string `json:"value"` }