mirror of
https://github.com/drone/drone-kaniko.git
synced 2026-06-04 10:14:55 +08:00
f83970e37a
* feat: [CI-18693]: Added oidc support for ACR * feat: [CI-19349]: error handling * feat: [CI-19349]: Refactored the code and added cli flags * feat: [CI-19349]: Added test cases * Update cmd/kaniko-acr/main.go * Update cmd/kaniko-acr/main.go * Update cmd/kaniko-acr/main.go * feat: [CI-19349]: changed the variable names * feat: [CI-18693]: Added error handling * feat: [CI-19349]: removed redundant code --------- Co-authored-by: OP (oppenheimer) <21008429+Ompragash@users.noreply.github.com>
73 lines
2.2 KiB
Go
73 lines
2.2 KiB
Go
package azure
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const DefaultResource = "https://management.azure.com/"
|
|
const defaultAuthorityHost = "https://login.microsoftonline.com"
|
|
const defaultHTTPTimeout = 30 * time.Second
|
|
|
|
// GetAADAccessTokenViaClientAssertion exchanges an external OIDC ID token for an Azure AD access token
|
|
|
|
func GetAADAccessTokenViaClientAssertion(ctx context.Context, tenantID, clientID, oidcToken, authorityHost string) (string, error) {
|
|
resource := DefaultResource
|
|
|
|
form := url.Values{
|
|
"client_id": {clientID},
|
|
"scope": {resource + ".default"},
|
|
"grant_type": {"client_credentials"},
|
|
"client_assertion_type": {"urn:ietf:params:oauth:client-assertion-type:jwt-bearer"},
|
|
"client_assertion": {oidcToken},
|
|
}
|
|
base := authorityHost
|
|
if strings.TrimSpace(base) == "" {
|
|
base = defaultAuthorityHost
|
|
}
|
|
base = strings.TrimRight(base, "/")
|
|
endpoint := fmt.Sprintf("%s/%s/oauth2/v2.0/token", base, tenantID)
|
|
client := &http.Client{Timeout: defaultHTTPTimeout}
|
|
req, err := http.NewRequestWithContext(ctx, "POST", endpoint, strings.NewReader(form.Encode()))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
req.Header.Set("Accept", "application/json")
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
var aadErr struct {
|
|
Error string `json:"error"`
|
|
ErrorDescription string `json:"error_description"`
|
|
}
|
|
limited := io.LimitedReader{R: resp.Body, N: 4096}
|
|
_ = json.NewDecoder(&limited).Decode(&aadErr)
|
|
if aadErr.Error != "" {
|
|
return "", fmt.Errorf("AAD token request failed: status=%d, error=%s", resp.StatusCode, aadErr.Error)
|
|
}
|
|
return "", fmt.Errorf("AAD token request failed: status=%d", resp.StatusCode)
|
|
}
|
|
var payload struct {
|
|
AccessToken string `json:"access_token"`
|
|
TokenType string `json:"token_type"`
|
|
ExpiresIn int `json:"expires_in"`
|
|
}
|
|
if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
|
|
return "", err
|
|
}
|
|
if payload.AccessToken == "" {
|
|
return "", fmt.Errorf("AAD token response missing access_token")
|
|
}
|
|
return payload.AccessToken, nil
|
|
}
|