From 96a5836e2683482ce9bfbdb9f4e7206323cd0102 Mon Sep 17 00:00:00 2001 From: clyang82 Date: Tue, 26 Nov 2024 20:32:59 +0800 Subject: [PATCH] Support az-entra auth Signed-off-by: clyang82 --- go.mod | 6 ++++ go.sum | 13 +++++++++ pkg/config/db.go | 38 +++++++++++++++++++++++--- pkg/constants/constants.go | 3 ++ templates/service-template-aro-hcp.yml | 1 + 5 files changed, 57 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 842b119d..cbc03d3d 100755 --- a/go.mod +++ b/go.mod @@ -3,6 +3,8 @@ module github.com/openshift-online/maestro go 1.22.5 require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 github.com/Masterminds/squirrel v1.5.3 github.com/auth0/go-jwt-middleware v0.0.0-20190805220309-36081240882b github.com/buraksezer/consistent v0.10.0 @@ -59,6 +61,8 @@ require ( require ( cloud.google.com/go/compute/metadata v0.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/antlr/antlr4 v0.0.0-20200712162734-eb1adaa8a7a6 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect @@ -90,6 +94,7 @@ require ( github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/cel-go v0.20.1 // indirect @@ -119,6 +124,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/openshift/api v0.0.0-20241001152557-e415140e5d5f // indirect github.com/openshift/client-go v0.0.0-20241001162912-da6d55e4611f // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkg/profile v1.7.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/go.sum b/go.sum index 6d37a926..8167e651 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,16 @@ cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7h cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 h1:H+U3Gk9zY56G3u872L82bk4thcsy2Gghb9ExT4Zvm1o= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0/go.mod h1:mgrmMSgaLp9hmax62XQTd0N4aAqSE5E0DulSpVYK7vc= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/squirrel v1.1.0/go.mod h1:yaPeOnPG5ZRwL9oKdTsO/prlkPbXWZlRVMQ/gGlzIuA= @@ -181,6 +189,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= @@ -458,6 +468,8 @@ github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzb github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -716,6 +728,7 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= diff --git a/pkg/config/db.go b/pkg/config/db.go index 65c95aed..08ab1837 100755 --- a/pkg/config/db.go +++ b/pkg/config/db.go @@ -1,8 +1,12 @@ package config import ( + "context" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/openshift-online/maestro/pkg/constants" "github.com/spf13/pflag" ) @@ -24,10 +28,16 @@ type DatabaseConfig struct { UsernameFile string `json:"username_file"` PasswordFile string `json:"password_file"` RootCertFile string `json:"certificate_file"` + + AuthMethod string `json:"auth_method"` + TokenRequestScope string `json:"token_request_scope"` } func NewDatabaseConfig() *DatabaseConfig { return &DatabaseConfig{ + AuthMethod: constants.AuthMethodPassword, + TokenRequestScope: "https://ossrdbms-aad.database.windows.net/.default", + Dialect: "postgres", SSLMode: "disable", Debug: false, @@ -43,6 +53,9 @@ func NewDatabaseConfig() *DatabaseConfig { } func (c *DatabaseConfig) AddFlags(fs *pflag.FlagSet) { + fs.StringVar(&c.AuthMethod, "db-auth-method", c.AuthMethod, "Configure the authentication to use password as the default and az-entra for Microsoft Entra Authentication in Azure PostgreSQL") + fs.StringVar(&c.TokenRequestScope, "db-token-request-scope", c.TokenRequestScope, "Configure the token request scope for Open-Source Relational Database Management Systems in Azure") + fs.StringVar(&c.HostFile, "db-host-file", c.HostFile, "Database host string file") fs.StringVar(&c.PortFile, "db-port-file", c.PortFile, "Database port file") fs.StringVar(&c.UsernameFile, "db-user-file", c.UsernameFile, "Database username file") @@ -50,7 +63,7 @@ func (c *DatabaseConfig) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&c.NameFile, "db-name-file", c.NameFile, "Database name file") fs.StringVar(&c.RootCertFile, "db-rootcert", c.RootCertFile, "Database root certificate file") fs.StringVar(&c.SSLMode, "db-sslmode", c.SSLMode, "Database ssl mode (disable | require | verify-ca | verify-full)") - fs.BoolVar(&c.Debug, "enable-db-debug", c.Debug, " framework's debug mode") + fs.BoolVar(&c.Debug, "enable-db-debug", c.Debug, "framework's debug mode") fs.IntVar(&c.MaxOpenConnections, "db-max-open-connections", c.MaxOpenConnections, "Maximum open DB connections for this instance") } @@ -70,9 +83,26 @@ func (c *DatabaseConfig) ReadFiles() error { return err } - err = readFileValueString(c.PasswordFile, &c.Password) - if err != nil { - return err + if c.AuthMethod == constants.AuthMethodMicrosoftEntra { + // ARO-HCP environment variable configuration is set by the Azure workload identity webhook. + // Use [WorkloadIdentityCredential] directly when not using the webhook or needing more control over its configuration. + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return err + } + // The access token can be expired. but the existing connections are not invalidated. + // TODO: how to reconnect due to the network is broken etc. Right now, gorm does not have this feature. + // refer to https://github.com/go-gorm/gorm/issues/5602 & https://github.com/go-gorm/gorm/pull/1721. + token, err := cred.GetToken(context.Background(), policy.TokenRequestOptions{Scopes: []string{c.TokenRequestScope}}) + if err != nil { + return err + } + c.Password = token.Token + } else { + err = readFileValueString(c.PasswordFile, &c.Password) + if err != nil { + return err + } } err = readFileValueString(c.NameFile, &c.Name) diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 6467883b..30877d12 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -2,4 +2,7 @@ package constants const ( DefaultSourceID = "maestro" + + AuthMethodPassword = "password" // Standard postgres username/password authentication. + AuthMethodMicrosoftEntra = "az-entra" // Microsoft Entra ID-based token authentication. ) diff --git a/templates/service-template-aro-hcp.yml b/templates/service-template-aro-hcp.yml index 90b5df81..441cfa89 100755 --- a/templates/service-template-aro-hcp.yml +++ b/templates/service-template-aro-hcp.yml @@ -184,6 +184,7 @@ objects: metadata: labels: app: maestro + azure.workload.identity/use: "true" # Required. Only pods with this label can use workload identity. spec: serviceAccountName: maestro volumes: