mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-26 04:10:08 +01:00
165 lines
4.9 KiB
Go
165 lines
4.9 KiB
Go
// Copyright 2023 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package oauth2adapt helps converts types used in [cloud.google.com/go/auth]
|
|
// and [golang.org/x/oauth2].
|
|
package oauth2adapt
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
|
|
"cloud.google.com/go/auth"
|
|
"golang.org/x/oauth2"
|
|
"golang.org/x/oauth2/google"
|
|
)
|
|
|
|
// TokenProviderFromTokenSource converts any [golang.org/x/oauth2.TokenSource]
|
|
// into a [cloud.google.com/go/auth.TokenProvider].
|
|
func TokenProviderFromTokenSource(ts oauth2.TokenSource) auth.TokenProvider {
|
|
return &tokenProviderAdapter{ts: ts}
|
|
}
|
|
|
|
type tokenProviderAdapter struct {
|
|
ts oauth2.TokenSource
|
|
}
|
|
|
|
// Token fulfills the [cloud.google.com/go/auth.TokenProvider] interface. It
|
|
// is a light wrapper around the underlying TokenSource.
|
|
func (tp *tokenProviderAdapter) Token(context.Context) (*auth.Token, error) {
|
|
tok, err := tp.ts.Token()
|
|
if err != nil {
|
|
var err2 *oauth2.RetrieveError
|
|
if ok := errors.As(err, &err2); ok {
|
|
return nil, AuthErrorFromRetrieveError(err2)
|
|
}
|
|
return nil, err
|
|
}
|
|
return &auth.Token{
|
|
Value: tok.AccessToken,
|
|
Type: tok.Type(),
|
|
Expiry: tok.Expiry,
|
|
}, nil
|
|
}
|
|
|
|
// TokenSourceFromTokenProvider converts any
|
|
// [cloud.google.com/go/auth.TokenProvider] into a
|
|
// [golang.org/x/oauth2.TokenSource].
|
|
func TokenSourceFromTokenProvider(tp auth.TokenProvider) oauth2.TokenSource {
|
|
return &tokenSourceAdapter{tp: tp}
|
|
}
|
|
|
|
type tokenSourceAdapter struct {
|
|
tp auth.TokenProvider
|
|
}
|
|
|
|
// Token fulfills the [golang.org/x/oauth2.TokenSource] interface. It
|
|
// is a light wrapper around the underlying TokenProvider.
|
|
func (ts *tokenSourceAdapter) Token() (*oauth2.Token, error) {
|
|
tok, err := ts.tp.Token(context.Background())
|
|
if err != nil {
|
|
var err2 *auth.Error
|
|
if ok := errors.As(err, &err2); ok {
|
|
return nil, AddRetrieveErrorToAuthError(err2)
|
|
}
|
|
return nil, err
|
|
}
|
|
return &oauth2.Token{
|
|
AccessToken: tok.Value,
|
|
TokenType: tok.Type,
|
|
Expiry: tok.Expiry,
|
|
}, nil
|
|
}
|
|
|
|
// AuthCredentialsFromOauth2Credentials converts a [golang.org/x/oauth2/google.Credentials]
|
|
// to a [cloud.google.com/go/auth.Credentials].
|
|
func AuthCredentialsFromOauth2Credentials(creds *google.Credentials) *auth.Credentials {
|
|
if creds == nil {
|
|
return nil
|
|
}
|
|
return auth.NewCredentials(&auth.CredentialsOptions{
|
|
TokenProvider: TokenProviderFromTokenSource(creds.TokenSource),
|
|
JSON: creds.JSON,
|
|
ProjectIDProvider: auth.CredentialsPropertyFunc(func(ctx context.Context) (string, error) {
|
|
return creds.ProjectID, nil
|
|
}),
|
|
UniverseDomainProvider: auth.CredentialsPropertyFunc(func(ctx context.Context) (string, error) {
|
|
return creds.GetUniverseDomain()
|
|
}),
|
|
})
|
|
}
|
|
|
|
// Oauth2CredentialsFromAuthCredentials converts a [cloud.google.com/go/auth.Credentials]
|
|
// to a [golang.org/x/oauth2/google.Credentials].
|
|
func Oauth2CredentialsFromAuthCredentials(creds *auth.Credentials) *google.Credentials {
|
|
if creds == nil {
|
|
return nil
|
|
}
|
|
// Throw away errors as old credentials are not request aware. Also, no
|
|
// network requests are currently happening for this use case.
|
|
projectID, _ := creds.ProjectID(context.Background())
|
|
|
|
return &google.Credentials{
|
|
TokenSource: TokenSourceFromTokenProvider(creds.TokenProvider),
|
|
ProjectID: projectID,
|
|
JSON: creds.JSON(),
|
|
UniverseDomainProvider: func() (string, error) {
|
|
return creds.UniverseDomain(context.Background())
|
|
},
|
|
}
|
|
}
|
|
|
|
type oauth2Error struct {
|
|
ErrorCode string `json:"error"`
|
|
ErrorDescription string `json:"error_description"`
|
|
ErrorURI string `json:"error_uri"`
|
|
}
|
|
|
|
// AddRetrieveErrorToAuthError returns the same error provided and adds a
|
|
// [golang.org/x/oauth2.RetrieveError] to the error chain by setting the `Err` field on the
|
|
// [cloud.google.com/go/auth.Error].
|
|
func AddRetrieveErrorToAuthError(err *auth.Error) *auth.Error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
e := &oauth2.RetrieveError{
|
|
Response: err.Response,
|
|
Body: err.Body,
|
|
}
|
|
err.Err = e
|
|
if len(err.Body) > 0 {
|
|
var oErr oauth2Error
|
|
// ignore the error as it only fills in extra details
|
|
json.Unmarshal(err.Body, &oErr)
|
|
e.ErrorCode = oErr.ErrorCode
|
|
e.ErrorDescription = oErr.ErrorDescription
|
|
e.ErrorURI = oErr.ErrorURI
|
|
}
|
|
return err
|
|
}
|
|
|
|
// AuthErrorFromRetrieveError returns an [cloud.google.com/go/auth.Error] that
|
|
// wraps the provided [golang.org/x/oauth2.RetrieveError].
|
|
func AuthErrorFromRetrieveError(err *oauth2.RetrieveError) *auth.Error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
return &auth.Error{
|
|
Response: err.Response,
|
|
Body: err.Body,
|
|
Err: err,
|
|
}
|
|
}
|