From 79822ead77d1651384e88ed661da03cb81fadbb7 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Tue, 15 Apr 2025 14:53:53 +0300 Subject: [PATCH 01/17] update dependencies --- go.mod | 4 +++- go.sum | 6 ++++++ token/token.go | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index f1cdd0d..cbe1ad8 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,14 @@ go 1.18 require ( github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 - github.com/redis/go-redis/v9 v9.5.3-0.20250331212737-c248425ade4a + github.com/redis/go-redis/v9 v9.5.3-0.20250415103233-40a89c56cc52 github.com/stretchr/testify v1.10.0 ) require ( + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.5.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 10a19fe..250f8b1 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,12 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkY github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 h1:8BKxhZZLX/WosEeoCvWysmKUscfa9v8LIPEEU0JjE2o= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -25,6 +29,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.5.3-0.20250331212737-c248425ade4a h1:R5xgk8m+CF7lVE0EGr+tLkT1eM3Zfd39BJfnANQqpKA= github.com/redis/go-redis/v9 v9.5.3-0.20250331212737-c248425ade4a/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/redis/go-redis/v9 v9.5.3-0.20250415103233-40a89c56cc52 h1:jRx2gINoJsGKxi/RYXCq1VneAAYes9JxUp13xH2oU2g= +github.com/redis/go-redis/v9 v9.5.3-0.20250415103233-40a89c56cc52/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= diff --git a/token/token.go b/token/token.go index 66bd100..e85a814 100644 --- a/token/token.go +++ b/token/token.go @@ -15,10 +15,10 @@ func New(username, password, rawToken string, expiresOn, receivedAt time.Time, t return &Token{ username: username, password: password, + rawToken: rawToken, expiresOn: expiresOn, receivedAt: receivedAt, ttl: ttl, - rawToken: rawToken, } } From 73f4132a3d71e4d6246f4eadda5e367166218349 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Tue, 15 Apr 2025 15:34:52 +0300 Subject: [PATCH 02/17] add custom identity provider example --- examples/custom_idp/go.mod | 25 +++++++++ examples/custom_idp/go.sum | 53 +++++++++++++++++++ examples/custom_idp/main.go | 101 ++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 examples/custom_idp/go.mod create mode 100644 examples/custom_idp/go.sum create mode 100644 examples/custom_idp/main.go diff --git a/examples/custom_idp/go.mod b/examples/custom_idp/go.mod new file mode 100644 index 0000000..05f6098 --- /dev/null +++ b/examples/custom_idp/go.mod @@ -0,0 +1,25 @@ +module custom_example + +go 1.23.4 + +require ( + github.com/redis-developer/go-redis-entraid v0.0.0-20250415111332-9d087bc29c12 + github.com/redis/go-redis/v9 v9.5.3-0.20250415103233-40a89c56cc52 +) + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect +) diff --git a/examples/custom_idp/go.sum b/examples/custom_idp/go.sum new file mode 100644 index 0000000..46a0b34 --- /dev/null +++ b/examples/custom_idp/go.sum @@ -0,0 +1,53 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 h1:iw4+KCeCoieuKodp1d5YhAa1TU/GgogCbw8RbGvsfLA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1/go.mod h1:AP8cDnDTGIVvayqKAhwzpcAyTJosXpvLYNmVFJb98x8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3 h1:BAUsn6/icUFtvUalVwCO0+hSF7qgU9DwwcEfCvtILtw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3/go.mod h1:QlAsNp4gk9zLD2wiZIvIuv699ynpZ2Tq2ZBp+6MrSEw= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 h1:8BKxhZZLX/WosEeoCvWysmKUscfa9v8LIPEEU0JjE2o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis-developer/go-redis-entraid v0.0.0-20250415111332-9d087bc29c12 h1:H5ZfgueBAxs2eAvXtCMEbT2/fLQz/wxW5Ds4c0uzl50= +github.com/redis-developer/go-redis-entraid v0.0.0-20250415111332-9d087bc29c12/go.mod h1:uXKLxCMUAu1VKgWdt8gWc4PWCygiL2pAI5XpnRSVc0w= +github.com/redis/go-redis/v9 v9.5.3-0.20250415103233-40a89c56cc52 h1:jRx2gINoJsGKxi/RYXCq1VneAAYes9JxUp13xH2oU2g= +github.com/redis/go-redis/v9 v9.5.3-0.20250415103233-40a89c56cc52/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/custom_idp/main.go b/examples/custom_idp/main.go new file mode 100644 index 0000000..9add99c --- /dev/null +++ b/examples/custom_idp/main.go @@ -0,0 +1,101 @@ +package main + +import ( + "context" + "fmt" + "strconv" + "strings" + "time" + + entraid "github.com/redis-developer/go-redis-entraid" + "github.com/redis-developer/go-redis-entraid/manager" + "github.com/redis-developer/go-redis-entraid/shared" + "github.com/redis-developer/go-redis-entraid/token" + redis "github.com/redis/go-redis/v9" +) + +func main() { + ctx := context.Background() + idp := NewFakeIdentityProvider("local", "pass") + parser := &fakeIdentityProviderResponseParser{} + // create token manager + + tm, err := manager.NewTokenManager(idp, manager.TokenManagerOptions{ + IdentityProviderResponseParser: parser, + }) + + cp, err := entraid.NewCredentialsProvider(tm, entraid.CredentialsProviderOptions{}) + if err != nil { + panic(err) + } + + redis := redis.NewClient(&redis.Options{ + Addr: ":6379", + StreamingCredentialsProvider: cp, + }) + + ok, err := redis.Ping(ctx).Result() + if err != nil { + panic(err) + } + fmt.Println("Ping result:", ok) +} + +var _ entraid.IdentityProvider = (*FakeIdentityProvider)(nil) + +type FakeIdentityProvider struct { + username string + password string +} + +// RequestToken simulates a request to an identity provider and returns a fake token. +// In a real implementation, this would involve making a network request to the identity provider. +func (f *FakeIdentityProvider) RequestToken() (entraid.IdentityProviderResponse, error) { + // Simulate a successful token request + return shared.NewIDPResponse( + shared.ResponseTypeRawToken, + fmt.Sprintf("%s:%s:%d", f.username, f.password, time.Now().Add(1*time.Hour).Unix()), + ) +} + +// NewFakeIdentityProvider creates a new instance of FakeIdentityProvider with the given username and password. +func NewFakeIdentityProvider(username, password string) *FakeIdentityProvider { + return &FakeIdentityProvider{ + username: username, + password: password, + } +} + +type fakeIdentityProviderResponseParser struct { +} + +// ParseResponse simulates the parsing of a response from an identity provider. +func (f *fakeIdentityProviderResponseParser) ParseResponse(response entraid.IdentityProviderResponse) (*token.Token, error) { + if response.Type() == shared.ResponseTypeRawToken { + rawToken := response.RawToken() + username, password := "", "" + var expiresOnUnix int64 + + // parse the raw token string + // assuming the format is "username:password:expiresOnUnix" + // where expiresOnUnix is a unix timestamp + parts := strings.Split(rawToken, ":") + if len(parts) != 3 { + return nil, fmt.Errorf("invalid raw token format") + } + username = parts[0] + password = parts[1] + expiresOnUnix, err := strconv.ParseInt(parts[2], 10, 64) + if err != nil { + return nil, fmt.Errorf("failed to parse raw token: %w", err) + } + + // convert the unix timestamp to time.Time + expiresOn := time.Unix(expiresOnUnix, 0) + now := time.Now() + return token.New(username, password, rawToken, expiresOn, now, int64(expiresOn.Sub(now).Seconds())), nil + } + return nil, fmt.Errorf("unsupported response type: %s", response.Type()) +} + +var _ entraid.IdentityProviderResponseParser = (*fakeIdentityProviderResponseParser)(nil) From e74a79e24d4e44be690f0721030929d0af8d8521 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Thu, 24 Apr 2025 15:36:33 +0300 Subject: [PATCH 03/17] add additional examples --- examples/confidential_identity/main.go | 45 ++++++++++++++++++++ examples/default_azure_identity/main.go | 38 +++++++++++++++++ examples/managed_identity/main.go | 55 +++++++++++++++++++++++++ go.mod | 2 + go.sum | 6 +++ 5 files changed, 146 insertions(+) create mode 100644 examples/confidential_identity/main.go create mode 100644 examples/default_azure_identity/main.go create mode 100644 examples/managed_identity/main.go diff --git a/examples/confidential_identity/main.go b/examples/confidential_identity/main.go new file mode 100644 index 0000000..bd40fdd --- /dev/null +++ b/examples/confidential_identity/main.go @@ -0,0 +1,45 @@ +package main + +import ( + "context" + "fmt" + + entraid "github.com/redis-developer/go-redis-entraid" + "github.com/redis-developer/go-redis-entraid/identity" + redis "github.com/redis/go-redis/v9" +) + +func main() { + ctx := context.Background() + + // Create a confidential identity credentials provider + // This example uses client secret authentication + cp, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialCredentialsProviderOptions{ + ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ + ClientID: "your-client-id", + ClientSecret: "your-client-secret", + CredentialsType: "ClientSecret", + Authority: identity.AuthorityConfiguration{ + AuthorityType: identity.AuthorityTypeMultiTenant, + TenantID: "your-tenant-id", + }, + Scopes: []string{"https://redis.azure.com/.default"}, + }, + }) + if err != nil { + panic(fmt.Errorf("failed to create confidential identity credentials provider: %w", err)) + } + + // Create Redis client with the credentials provider + redisClient := redis.NewClient(&redis.Options{ + Addr: "your-redis-host:6379", + StreamingCredentialsProvider: cp, + }) + + // Test the connection + ok, err := redisClient.Ping(ctx).Result() + if err != nil { + panic(fmt.Errorf("failed to ping Redis: %w", err)) + } + fmt.Println("Ping result:", ok) +} diff --git a/examples/default_azure_identity/main.go b/examples/default_azure_identity/main.go new file mode 100644 index 0000000..4bd1e53 --- /dev/null +++ b/examples/default_azure_identity/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "context" + "fmt" + + entraid "github.com/redis-developer/go-redis-entraid" + "github.com/redis-developer/go-redis-entraid/identity" + redis "github.com/redis/go-redis/v9" +) + +func main() { + ctx := context.Background() + + // Create a default azure identity credentials provider + // This example uses the default Azure identity chain + cp, err := entraid.NewDefaultAzureCredentialsProvider(entraid.DefaultAzureCredentialsProviderOptions{ + DefaultAzureIdentityProviderOptions: identity.DefaultAzureIdentityProviderOptions{ + Scopes: []string{"https://redis.azure.com/.default"}, + }, + }) + if err != nil { + panic(fmt.Errorf("failed to create default azure identity credentials provider: %w", err)) + } + + // Create Redis client with the credentials provider + redisClient := redis.NewClient(&redis.Options{ + Addr: "your-redis-host:6379", + StreamingCredentialsProvider: cp, + }) + + // Test the connection + ok, err := redisClient.Ping(ctx).Result() + if err != nil { + panic(fmt.Errorf("failed to ping Redis: %w", err)) + } + fmt.Println("Ping result:", ok) +} diff --git a/examples/managed_identity/main.go b/examples/managed_identity/main.go new file mode 100644 index 0000000..833d791 --- /dev/null +++ b/examples/managed_identity/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "context" + "fmt" + + entraid "github.com/redis-developer/go-redis-entraid" + "github.com/redis-developer/go-redis-entraid/identity" + redis "github.com/redis/go-redis/v9" +) + +func main() { + ctx := context.Background() + + // Example 1: System-assigned managed identity + // This is the simplest configuration, as it uses the system-assigned identity + // automatically managed by Azure + systemAssignedCP, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedIdentityCredentialsProviderOptions{ + ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ + ManagedIdentityType: identity.SystemAssignedIdentity, + Scopes: []string{"https://redis.azure.com/.default"}, + }, + }) + if err != nil { + panic(fmt.Errorf("failed to create system-assigned managed identity credentials provider: %w", err)) + } + + // Example 2: User-assigned managed identity + // Uncomment and use this example if you want to use a user-assigned managed identity + /* + userAssignedCP, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedIdentityCredentialsProviderOptions{ + ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ + ManagedIdentityType: identity.UserAssignedIdentity, + UserAssignedClientID: "your-user-assigned-identity-client-id", + Scopes: []string{"https://redis.azure.com/.default"}, + }, + }) + if err != nil { + panic(fmt.Errorf("failed to create user-assigned managed identity credentials provider: %w", err)) + } + */ + + // Create Redis client with the credentials provider + redisClient := redis.NewClient(&redis.Options{ + Addr: "your-redis-host:6379", + StreamingCredentialsProvider: systemAssignedCP, // Change to userAssignedCP if using user-assigned identity + }) + + // Test the connection + ok, err := redisClient.Ping(ctx).Result() + if err != nil { + panic(fmt.Errorf("failed to ping Redis: %w", err)) + } + fmt.Println("Ping result:", ok) +} diff --git a/go.mod b/go.mod index 7e908f0..b59f728 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,9 @@ require ( ) require ( + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.5.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 36c644a..0d49fab 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,14 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkY github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 h1:8BKxhZZLX/WosEeoCvWysmKUscfa9v8LIPEEU0JjE2o= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= From e44f8483b3f399f8140e82604b5df9b9c631c77b Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Fri, 25 Apr 2025 16:08:51 +0300 Subject: [PATCH 04/17] change client variable name --- examples/custom_idp/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/custom_idp/main.go b/examples/custom_idp/main.go index 9add99c..c6c6d58 100644 --- a/examples/custom_idp/main.go +++ b/examples/custom_idp/main.go @@ -29,12 +29,12 @@ func main() { panic(err) } - redis := redis.NewClient(&redis.Options{ + client := redis.NewClient(&redis.Options{ Addr: ":6379", StreamingCredentialsProvider: cp, }) - ok, err := redis.Ping(ctx).Result() + ok, err := client.Ping(ctx).Result() if err != nil { panic(err) } From c1ae7711b8ce6f35fe1823f3b5276b6defc7104c Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Mon, 19 May 2025 18:07:27 +0300 Subject: [PATCH 05/17] chore(exampels): Add runnable examples --- README.md | 57 +++++---- examples/confidential_identity/main.go | 45 ------- examples/entraid/clientcert/go.mod | 32 +++++ examples/entraid/clientcert/go.sum | 53 ++++++++ examples/entraid/clientcert/main.go | 116 ++++++++++++++++++ examples/entraid/clientsecret/go.mod | 32 +++++ examples/entraid/clientsecret/go.sum | 53 ++++++++ examples/entraid/clientsecret/main.go | 94 ++++++++++++++ examples/entraid/config/config.go | 90 ++++++++++++++ examples/entraid/config/go.mod | 3 + examples/entraid/defaultcredentials/go.mod | 32 +++++ examples/entraid/defaultcredentials/go.sum | 52 ++++++++ examples/entraid/defaultcredentials/main.go | 65 ++++++++++ examples/entraid/endpoints.json | 109 ++++++++++++++++ .../entraid/managedidentity_system/go.mod | 32 +++++ .../entraid/managedidentity_system/go.sum | 53 ++++++++ .../entraid/managedidentity_system/main.go | 88 +++++++++++++ examples/entraid/managedidentity_user/go.mod | 32 +++++ examples/entraid/managedidentity_user/go.sum | 53 ++++++++ examples/entraid/managedidentity_user/main.go | 91 ++++++++++++++ examples/entraid/run_examples.sh | 59 +++++++++ examples/managed_identity/main.go | 55 --------- go.mod | 2 +- go.sum | 2 + 24 files changed, 1178 insertions(+), 122 deletions(-) delete mode 100644 examples/confidential_identity/main.go create mode 100644 examples/entraid/clientcert/go.mod create mode 100644 examples/entraid/clientcert/go.sum create mode 100644 examples/entraid/clientcert/main.go create mode 100644 examples/entraid/clientsecret/go.mod create mode 100644 examples/entraid/clientsecret/go.sum create mode 100644 examples/entraid/clientsecret/main.go create mode 100644 examples/entraid/config/config.go create mode 100644 examples/entraid/config/go.mod create mode 100644 examples/entraid/defaultcredentials/go.mod create mode 100644 examples/entraid/defaultcredentials/go.sum create mode 100644 examples/entraid/defaultcredentials/main.go create mode 100644 examples/entraid/endpoints.json create mode 100644 examples/entraid/managedidentity_system/go.mod create mode 100644 examples/entraid/managedidentity_system/go.sum create mode 100644 examples/entraid/managedidentity_system/main.go create mode 100644 examples/entraid/managedidentity_user/go.mod create mode 100644 examples/entraid/managedidentity_user/go.sum create mode 100644 examples/entraid/managedidentity_user/main.go create mode 100755 examples/entraid/run_examples.sh delete mode 100644 examples/managed_identity/main.go diff --git a/README.md b/README.md index f485829..7a1c328 100644 --- a/README.md +++ b/README.md @@ -411,10 +411,10 @@ authority := identity.AuthorityConfiguration{ ```go // Create provider for system assigned identity provider, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedIdentityCredentialsProviderOptions{ - CredentialsProviderOptions: entraid.CredentialsProviderOptions{ - ClientID: os.Getenv("AZURE_CLIENT_ID"), + ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ + ManagedIdentityType: identity.SystemAssignedIdentity, + Scopes: []string{"https://redis.azure.com/.default"}, }, - ManagedIdentityType: identity.SystemAssignedIdentity, }) ``` @@ -425,23 +425,27 @@ provider, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedId CredentialsProviderOptions: entraid.CredentialsProviderOptions{ ClientID: os.Getenv("AZURE_CLIENT_ID"), }, - ManagedIdentityType: identity.UserAssignedIdentity, - UserAssignedClientID: os.Getenv("USER_ASSIGNED_CLIENT_ID"), + ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ + ManagedIdentityType: identity.UserAssignedIdentity, + UserAssignedClientID: os.Getenv("AZURE_USER_ASSIGNED_MANAGED_ID"), + Scopes: []string{"https://redis.azure.com/.default"}, + }, }) ``` ### Client Secret Authentication ```go // Create provider for client secret authentication -provider, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialIdentityProviderOptions{ - CredentialsProviderOptions: entraid.CredentialsProviderOptions{ +provider, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialCredentialsProviderOptions{ + ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ ClientID: os.Getenv("AZURE_CLIENT_ID"), - }, - CredentialsType: identity.ClientSecretCredentialType, - ClientSecret: os.Getenv("AZURE_CLIENT_SECRET"), - Authority: identity.AuthorityConfiguration{ - AuthorityType: identity.AuthorityTypeDefault, - TenantID: os.Getenv("AZURE_TENANT_ID"), + ClientSecret: os.Getenv("AZURE_CLIENT_SECRET"), + CredentialsType: identity.ClientSecretCredentialType, + Authority: identity.AuthorityConfiguration{ + AuthorityType: identity.AuthorityTypeMultiTenant, + TenantID: os.Getenv("AZURE_TENANT_ID"), + }, + Scopes: []string{"https://redis.azure.com/.default"}, }, }) ``` @@ -454,16 +458,27 @@ if err != nil { log.Fatal(err) } -provider, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialIdentityProviderOptions{ - CredentialsProviderOptions: entraid.CredentialsProviderOptions{ +provider, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialCredentialsProviderOptions{ + ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ ClientID: os.Getenv("AZURE_CLIENT_ID"), + CredentialsType: identity.ClientCertificateCredentialType, + Authority: identity.AuthorityConfiguration{ + AuthorityType: identity.AuthorityTypeMultiTenant, + TenantID: os.Getenv("AZURE_TENANT_ID"), + }, + Scopes: []string{"https://redis.azure.com/.default"}, + ClientCert: []*x509.Certificate{cert.Leaf}, + ClientPrivateKey: cert.PrivateKey, }, - CredentialsType: identity.ClientCertificateCredentialType, - ClientCert: []*x509.Certificate{cert.Leaf}, - ClientPrivateKey: cert.PrivateKey, - Authority: identity.AuthorityConfiguration{ - AuthorityType: identity.AuthorityTypeDefault, - TenantID: os.Getenv("AZURE_TENANT_ID"), +}) +``` + +### Default Azure Identity +```go +// Create a default credentials provider +provider, err := entraid.NewDefaultAzureCredentialsProvider(entraid.DefaultAzureCredentialsProviderOptions{ + DefaultAzureIdentityProviderOptions: identity.DefaultAzureIdentityProviderOptions{ + Scopes: []string{"https://redis.azure.com/.default"}, }, }) ``` diff --git a/examples/confidential_identity/main.go b/examples/confidential_identity/main.go deleted file mode 100644 index bd40fdd..0000000 --- a/examples/confidential_identity/main.go +++ /dev/null @@ -1,45 +0,0 @@ -package main - -import ( - "context" - "fmt" - - entraid "github.com/redis-developer/go-redis-entraid" - "github.com/redis-developer/go-redis-entraid/identity" - redis "github.com/redis/go-redis/v9" -) - -func main() { - ctx := context.Background() - - // Create a confidential identity credentials provider - // This example uses client secret authentication - cp, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialCredentialsProviderOptions{ - ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ - ClientID: "your-client-id", - ClientSecret: "your-client-secret", - CredentialsType: "ClientSecret", - Authority: identity.AuthorityConfiguration{ - AuthorityType: identity.AuthorityTypeMultiTenant, - TenantID: "your-tenant-id", - }, - Scopes: []string{"https://redis.azure.com/.default"}, - }, - }) - if err != nil { - panic(fmt.Errorf("failed to create confidential identity credentials provider: %w", err)) - } - - // Create Redis client with the credentials provider - redisClient := redis.NewClient(&redis.Options{ - Addr: "your-redis-host:6379", - StreamingCredentialsProvider: cp, - }) - - // Test the connection - ok, err := redisClient.Ping(ctx).Result() - if err != nil { - panic(fmt.Errorf("failed to ping Redis: %w", err)) - } - fmt.Println("Ping result:", ok) -} diff --git a/examples/entraid/clientcert/go.mod b/examples/entraid/clientcert/go.mod new file mode 100644 index 0000000..6fd020f --- /dev/null +++ b/examples/entraid/clientcert/go.mod @@ -0,0 +1,32 @@ +module clientcert + +go 1.23.4 + +require ( + config v0.0.0 + github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 + github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b +) + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect +) + +replace ( + config => ../config + github.com/redis-developer/go-redis-entraid => ../../../ + github.com/redis/go-redis/v9 => github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b +) diff --git a/examples/entraid/clientcert/go.sum b/examples/entraid/clientcert/go.sum new file mode 100644 index 0000000..99724cd --- /dev/null +++ b/examples/entraid/clientcert/go.sum @@ -0,0 +1,53 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 h1:iw4+KCeCoieuKodp1d5YhAa1TU/GgogCbw8RbGvsfLA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1/go.mod h1:AP8cDnDTGIVvayqKAhwzpcAyTJosXpvLYNmVFJb98x8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3 h1:BAUsn6/icUFtvUalVwCO0+hSF7qgU9DwwcEfCvtILtw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3/go.mod h1:QlAsNp4gk9zLD2wiZIvIuv699ynpZ2Tq2ZBp+6MrSEw= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 h1:8BKxhZZLX/WosEeoCvWysmKUscfa9v8LIPEEU0JjE2o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 h1:l/sz658wqg5ZxqT1cSrmTxGAEXVoBpVOjsZUgMHSJYw= +github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07/go.mod h1:4DrBBopECIq9LRo1hok3rgXUC4AGBhnZiz0Rea2tikc= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/entraid/clientcert/main.go b/examples/entraid/clientcert/main.go new file mode 100644 index 0000000..6e50485 --- /dev/null +++ b/examples/entraid/clientcert/main.go @@ -0,0 +1,116 @@ +package main + +import ( + "context" + "crypto/x509" + "encoding/pem" + "fmt" + "log" + "os" + + "config" + + entraid "github.com/redis-developer/go-redis-entraid" + "github.com/redis-developer/go-redis-entraid/identity" + "github.com/redis/go-redis/v9" +) + +func main() { + ctx := context.Background() + + // Load configuration + cfg, err := config.LoadConfig(os.Getenv("REDIS_ENDPOINTS_CONFIG_PATH")) + if err != nil { + log.Fatalf("Failed to load config: %v", err) + } + + // Create a confidential identity credentials provider with certificate authentication + cp, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialCredentialsProviderOptions{ + ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ + ClientID: cfg.AzureClientID, + ClientSecret: cfg.AzureClientSecret, + CredentialsType: "Certificate", + Authority: identity.AuthorityConfiguration{ + AuthorityType: identity.AuthorityTypeMultiTenant, + TenantID: cfg.AzureTenantID, + }, + Scopes: cfg.GetRedisScopes(), + ClientCert: parseCertificates(cfg.AzureCert), + ClientPrivateKey: []byte(cfg.AzurePrivateKey), + }, + }) + if err != nil { + log.Fatalf("Failed to create credentials provider: %v", err) + } + + // Create Redis client with streaming credentials provider + redisClient := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: []string{cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]}, + StreamingCredentialsProvider: cp, + }) + + // Create second Redis client for cluster + clusterClient := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: cfg.Endpoints["cluster-entraid-acl"].Endpoints, + StreamingCredentialsProvider: cp, + }) + + // Test the connection + pong, err := redisClient.Ping(ctx).Result() + if err != nil { + log.Fatalf("Failed to ping Redis: %v", err) + } + fmt.Printf("Successfully connected to Redis standalone: %s\n", pong) + + // Test cluster connection + clusterPong, err := clusterClient.Ping(ctx).Result() + if err != nil { + log.Fatalf("Failed to ping Redis cluster: %v", err) + } + fmt.Printf("Successfully connected to Redis cluster: %s\n", clusterPong) + + // Set a test key + err = redisClient.Set(ctx, "test-key", "test-value", 0).Err() + if err != nil { + log.Fatalf("Failed to set test key: %v", err) + } + + // Get the test key + val, err := redisClient.Get(ctx, "test-key").Result() + if err != nil { + log.Fatalf("Failed to get test key: %v", err) + } + fmt.Printf("Retrieved value from standalone: %s\n", val) + + // Set a test key in cluster + err = clusterClient.Set(ctx, "test-key", "test-value", 0).Err() + if err != nil { + log.Fatalf("Failed to set test key in cluster: %v", err) + } + + // Get the test key from cluster + clusterVal, err := clusterClient.Get(ctx, "test-key").Result() + if err != nil { + log.Fatalf("Failed to get test key from cluster: %v", err) + } + fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) +} + +func parseCertificates(pemData string) []*x509.Certificate { + var certs []*x509.Certificate + for { + block, rest := pem.Decode([]byte(pemData)) + if block == nil { + break + } + if block.Type == "CERTIFICATE" { + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + log.Fatalf("Failed to parse certificate: %v", err) + } + certs = append(certs, cert) + } + pemData = string(rest) + } + return certs +} diff --git a/examples/entraid/clientsecret/go.mod b/examples/entraid/clientsecret/go.mod new file mode 100644 index 0000000..8d86740 --- /dev/null +++ b/examples/entraid/clientsecret/go.mod @@ -0,0 +1,32 @@ +module clientsecret + +go 1.23.4 + +require ( + config v0.0.0 + github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 + github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b +) + +replace ( + config => ../config + github.com/redis-developer/go-redis-entraid => ../../../ + github.com/redis/go-redis/v9 => github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b +) + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect +) diff --git a/examples/entraid/clientsecret/go.sum b/examples/entraid/clientsecret/go.sum new file mode 100644 index 0000000..99724cd --- /dev/null +++ b/examples/entraid/clientsecret/go.sum @@ -0,0 +1,53 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 h1:iw4+KCeCoieuKodp1d5YhAa1TU/GgogCbw8RbGvsfLA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1/go.mod h1:AP8cDnDTGIVvayqKAhwzpcAyTJosXpvLYNmVFJb98x8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3 h1:BAUsn6/icUFtvUalVwCO0+hSF7qgU9DwwcEfCvtILtw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3/go.mod h1:QlAsNp4gk9zLD2wiZIvIuv699ynpZ2Tq2ZBp+6MrSEw= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 h1:8BKxhZZLX/WosEeoCvWysmKUscfa9v8LIPEEU0JjE2o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 h1:l/sz658wqg5ZxqT1cSrmTxGAEXVoBpVOjsZUgMHSJYw= +github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07/go.mod h1:4DrBBopECIq9LRo1hok3rgXUC4AGBhnZiz0Rea2tikc= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/entraid/clientsecret/main.go b/examples/entraid/clientsecret/main.go new file mode 100644 index 0000000..4b4f21c --- /dev/null +++ b/examples/entraid/clientsecret/main.go @@ -0,0 +1,94 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + + "config" + + entraid "github.com/redis-developer/go-redis-entraid" + "github.com/redis-developer/go-redis-entraid/identity" + "github.com/redis/go-redis/v9" +) + +func main() { + ctx := context.Background() + + // Load configuration + cfg, err := config.LoadConfig(os.Getenv("REDIS_ENDPOINTS_CONFIG_PATH")) + if err != nil { + log.Fatalf("Failed to load config: %v", err) + } + + // Create a confidential identity credentials provider + // This example uses client secret authentication + cp, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialCredentialsProviderOptions{ + ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ + ClientID: cfg.AzureClientID, + ClientSecret: cfg.AzureClientSecret, + CredentialsType: "ClientSecret", + Authority: identity.AuthorityConfiguration{ + AuthorityType: identity.AuthorityTypeMultiTenant, + TenantID: cfg.AzureTenantID, + }, + Scopes: cfg.GetRedisScopes(), + }, + }) + if err != nil { + log.Fatalf("Failed to create credentials provider: %v", err) + } + + // Create Redis client with streaming credentials provider + redisClient := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: []string{cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]}, + StreamingCredentialsProvider: cp, + }) + + // Create second Redis client for cluster + clusterClient := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: cfg.Endpoints["cluster-entraid-acl"].Endpoints, + StreamingCredentialsProvider: cp, + }) + + // Test the connection + pong, err := redisClient.Ping(ctx).Result() + if err != nil { + log.Fatalf("Failed to ping Redis: %v", err) + } + fmt.Printf("Successfully connected to Redis standalone: %s\n", pong) + + // Test cluster connection + clusterPong, err := clusterClient.Ping(ctx).Result() + if err != nil { + log.Fatalf("Failed to ping Redis cluster: %v", err) + } + fmt.Printf("Successfully connected to Redis cluster: %s\n", clusterPong) + + // Set a test key + err = redisClient.Set(ctx, "test-key", "test-value", 0).Err() + if err != nil { + log.Fatalf("Failed to set test key: %v", err) + } + + // Get the test key + val, err := redisClient.Get(ctx, "test-key").Result() + if err != nil { + log.Fatalf("Failed to get test key: %v", err) + } + fmt.Printf("Retrieved value from standalone: %s\n", val) + + // Set a test key in cluster + err = clusterClient.Set(ctx, "test-key", "test-value", 0).Err() + if err != nil { + log.Fatalf("Failed to set test key in cluster: %v", err) + } + + // Get the test key from cluster + clusterVal, err := clusterClient.Get(ctx, "test-key").Result() + if err != nil { + log.Fatalf("Failed to get test key from cluster: %v", err) + } + fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) +} diff --git a/examples/entraid/config/config.go b/examples/entraid/config/config.go new file mode 100644 index 0000000..5ce91bc --- /dev/null +++ b/examples/entraid/config/config.go @@ -0,0 +1,90 @@ +package config + +import ( + "encoding/json" + "os" + "strings" +) + +// RedisEndpoint represents a Redis endpoint configuration +// It is loaded from a JSON file +type RedisEndpoint struct { + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + TLS bool `json:"tls"` + CertificatesLocation string `json:"certificatesLocation,omitempty"` + Endpoints []string `json:"endpoints"` +} + +// EntraidConfig represents the configuration for Entra ID authentication +// It is loaded from a both JSON file and environment variables +type EntraidConfig struct { + // JSON config fields + Endpoints map[string]RedisEndpoint `json:"endpoints"` + + // Azure environment variables + AzureClientID string `json:"-"` + AzureClientSecret string `json:"-"` + AzureTenantID string `json:"-"` + AzureAuthority string `json:"-"` + AzureRedisScopes string `json:"-"` + AzureCert string `json:"-"` + AzurePrivateKey string `json:"-"` + AzureUserAssignedManagedID string `json:"-"` +} + +// LoadConfig loads the configuration from both JSON file and environment variables +func LoadConfig(configPath string) (*EntraidConfig, error) { + config := &EntraidConfig{} + + // Load from JSON file first + if configPath == "" { + configPath = "../endpoints.json" // Default path if not set + } + + file, err := os.Open(configPath) + if err == nil { + defer file.Close() + decoder := json.NewDecoder(file) + err = decoder.Decode(config) + if err != nil { + return nil, err + } + } + + // Override with environment variables if they exist + if envClientID := os.Getenv("AZURE_CLIENT_ID"); envClientID != "" { + config.AzureClientID = envClientID + } + if envClientSecret := os.Getenv("AZURE_CLIENT_SECRET"); envClientSecret != "" { + config.AzureClientSecret = envClientSecret + } + if envTenantID := os.Getenv("AZURE_TENANT_ID"); envTenantID != "" { + config.AzureTenantID = envTenantID + } + if envAuthority := os.Getenv("AZURE_AUTHORITY"); envAuthority != "" { + config.AzureAuthority = envAuthority + } + if envRedisScopes := os.Getenv("AZURE_REDIS_SCOPES"); envRedisScopes != "" { + config.AzureRedisScopes = envRedisScopes + } + if envCert := os.Getenv("AZURE_CERT"); envCert != "" { + config.AzureCert = envCert + } + if envPrivateKey := os.Getenv("AZURE_PRIVATE_KEY"); envPrivateKey != "" { + config.AzurePrivateKey = envPrivateKey + } + if envManagedID := os.Getenv("AZURE_USER_ASSIGNED_MANAGED_ID"); envManagedID != "" { + config.AzureUserAssignedManagedID = envManagedID + } + + return config, nil +} + +// GetRedisScopes returns the Redis scopes as a string slice +func (c *EntraidConfig) GetRedisScopes() []string { + if c.AzureRedisScopes == "" { + return []string{"https://redis.azure.com/.default"} // Default scope + } + return strings.Split(c.AzureRedisScopes, ",") +} diff --git a/examples/entraid/config/go.mod b/examples/entraid/config/go.mod new file mode 100644 index 0000000..b62db2e --- /dev/null +++ b/examples/entraid/config/go.mod @@ -0,0 +1,3 @@ +module config + +go 1.23.4 \ No newline at end of file diff --git a/examples/entraid/defaultcredentials/go.mod b/examples/entraid/defaultcredentials/go.mod new file mode 100644 index 0000000..4526824 --- /dev/null +++ b/examples/entraid/defaultcredentials/go.mod @@ -0,0 +1,32 @@ +module defaultcredentials + +go 1.23.4 + +require ( + config v0.0.0 + github.com/redis-developer/go-redis-entraid v0.0.0-00010101000000-000000000000 + github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b +) + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect +) + +replace ( + config => ../config + github.com/redis-developer/go-redis-entraid => ../../../ + github.com/redis/go-redis/v9 => github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b +) diff --git a/examples/entraid/defaultcredentials/go.sum b/examples/entraid/defaultcredentials/go.sum new file mode 100644 index 0000000..3b7d2aa --- /dev/null +++ b/examples/entraid/defaultcredentials/go.sum @@ -0,0 +1,52 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 h1:iw4+KCeCoieuKodp1d5YhAa1TU/GgogCbw8RbGvsfLA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1/go.mod h1:AP8cDnDTGIVvayqKAhwzpcAyTJosXpvLYNmVFJb98x8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3 h1:BAUsn6/icUFtvUalVwCO0+hSF7qgU9DwwcEfCvtILtw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3/go.mod h1:QlAsNp4gk9zLD2wiZIvIuv699ynpZ2Tq2ZBp+6MrSEw= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 h1:8BKxhZZLX/WosEeoCvWysmKUscfa9v8LIPEEU0JjE2o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 h1:l/sz658wqg5ZxqT1cSrmTxGAEXVoBpVOjsZUgMHSJYw= +github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07/go.mod h1:4DrBBopECIq9LRo1hok3rgXUC4AGBhnZiz0Rea2tikc= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/entraid/defaultcredentials/main.go b/examples/entraid/defaultcredentials/main.go new file mode 100644 index 0000000..9d56cf0 --- /dev/null +++ b/examples/entraid/defaultcredentials/main.go @@ -0,0 +1,65 @@ +package main + +import ( + "context" + "fmt" + "log" + + "config" + + entraid "github.com/redis-developer/go-redis-entraid" + "github.com/redis-developer/go-redis-entraid/identity" + "github.com/redis/go-redis/v9" +) + +func main() { + ctx := context.Background() + + // Load configuration + cfg, err := config.LoadConfig("") + if err != nil { + log.Fatalf("Failed to load config: %v", err) + } + + // Create a default credentials provider + // This will try different authentication methods in sequence: + // 1. Environment variables (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, etc.) + // 2. Managed Identity (system-assigned or user-assigned) + // 3. Azure CLI credentials + // 4. Visual Studio Code credentials + cp, err := entraid.NewDefaultAzureCredentialsProvider(entraid.DefaultAzureCredentialsProviderOptions{ + DefaultAzureIdentityProviderOptions: identity.DefaultAzureIdentityProviderOptions{ + Scopes: []string{"https://redis.azure.com/.default"}, + }, + }) + if err != nil { + log.Fatalf("Failed to create credentials provider: %v", err) + } + + // Create Redis client with streaming credentials provider + redisClient := redis.NewClusterClient(&redis.ClusterOptions{ + DisableIdentity: true, + Addrs: []string{cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]}, + StreamingCredentialsProvider: cp, + }) + + // Test the connection + pong, err := redisClient.Ping(ctx).Result() + if err != nil { + log.Fatalf("Failed to ping Redis: %v", err) + } + fmt.Printf("Successfully connected to Redis: %s\n", pong) + + // Set a test key + err = redisClient.Set(ctx, "test-key", "test-value", 0).Err() + if err != nil { + log.Fatalf("Failed to set test key: %v", err) + } + + // Get the test key + val, err := redisClient.Get(ctx, "test-key").Result() + if err != nil { + log.Fatalf("Failed to get test key: %v", err) + } + fmt.Printf("Retrieved value: %s\n", val) +} diff --git a/examples/entraid/endpoints.json b/examples/entraid/endpoints.json new file mode 100644 index 0000000..45555a4 --- /dev/null +++ b/examples/entraid/endpoints.json @@ -0,0 +1,109 @@ +{ + "standalone0": { + "password": "foobared", + "tls": false, + "endpoints": [ + "redis://localhost:6379" + ] + }, + "standalone0-tls": { + "username": "default", + "password": "foobared", + "tls": true, + "certificatesLocation": "redis1-2-5-8-sentinel/work/tls", + "endpoints": [ + "rediss://localhost:6390" + ] + }, + "standalone0-acl": { + "username": "acljedis", + "password": "fizzbuzz", + "tls": false, + "endpoints": [ + "redis://localhost:6379" + ] + }, + "standalone0-acl-tls": { + "username": "acljedis", + "password": "fizzbuzz", + "tls": true, + "certificatesLocation": "redis1-2-5-8-sentinel/work/tls", + "endpoints": [ + "rediss://localhost:6390" + ] + }, + "standalone1": { + "username": "default", + "password": "foobared", + "tls": false, + "endpoints": [ + "redis://localhost:6380" + ] + }, + "standalone2-primary": { + "username": "default", + "password": "foobared", + "tls": false, + "endpoints": [ + "redis://localhost:6381" + ] + }, + "standalone3-replica-of-standalone2": { + "username": "default", + "password": "foobared", + "tls": false, + "endpoints": [ + "redis://localhost:6382" + ] + }, + "standalone4-replica-of-standalone1": { + "username": "default", + "password": "foobared", + "tls": false, + "endpoints": [ + "redis://localhost:6383" + ] + }, + "standalone5-primary": { + "username": "default", + "password": "foobared", + "tls": false, + "endpoints": [ + "redis://localhost:6384" + ] + }, + "standalone6-replica-of-standalone5": { + "username": "default", + "password": "foobared", + "tls": false, + "endpoints": [ + "redis://localhost:6385" + ] + }, + "standalone7-with-lfu-policy": { + "username": "default", + "password": "foobared", + "tls": false, + "endpoints": [ + "redis://localhost:6386" + ] + }, + "standalone9": { + "tls": false, + "endpoints": [ + "redis://localhost:6388" + ] + }, + "standalone10-replica-of-standalone9": { + "tls": false, + "endpoints": [ + "redis://localhost:6389" + ] + }, + "modules-docker": { + "tls": false, + "endpoints": [ + "redis://localhost:6479" + ] + } +} \ No newline at end of file diff --git a/examples/entraid/managedidentity_system/go.mod b/examples/entraid/managedidentity_system/go.mod new file mode 100644 index 0000000..8198671 --- /dev/null +++ b/examples/entraid/managedidentity_system/go.mod @@ -0,0 +1,32 @@ +module managedidentity_system + +go 1.23.4 + +require ( + config v0.0.0 + github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 + github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b +) + +replace ( + config => ../config + github.com/redis-developer/go-redis-entraid => ../../../ + github.com/redis/go-redis/v9 => github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b +) + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect +) diff --git a/examples/entraid/managedidentity_system/go.sum b/examples/entraid/managedidentity_system/go.sum new file mode 100644 index 0000000..99724cd --- /dev/null +++ b/examples/entraid/managedidentity_system/go.sum @@ -0,0 +1,53 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 h1:iw4+KCeCoieuKodp1d5YhAa1TU/GgogCbw8RbGvsfLA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1/go.mod h1:AP8cDnDTGIVvayqKAhwzpcAyTJosXpvLYNmVFJb98x8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3 h1:BAUsn6/icUFtvUalVwCO0+hSF7qgU9DwwcEfCvtILtw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3/go.mod h1:QlAsNp4gk9zLD2wiZIvIuv699ynpZ2Tq2ZBp+6MrSEw= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 h1:8BKxhZZLX/WosEeoCvWysmKUscfa9v8LIPEEU0JjE2o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 h1:l/sz658wqg5ZxqT1cSrmTxGAEXVoBpVOjsZUgMHSJYw= +github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07/go.mod h1:4DrBBopECIq9LRo1hok3rgXUC4AGBhnZiz0Rea2tikc= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/entraid/managedidentity_system/main.go b/examples/entraid/managedidentity_system/main.go new file mode 100644 index 0000000..e0d1e58 --- /dev/null +++ b/examples/entraid/managedidentity_system/main.go @@ -0,0 +1,88 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + + "config" + + entraid "github.com/redis-developer/go-redis-entraid" + "github.com/redis-developer/go-redis-entraid/identity" + "github.com/redis/go-redis/v9" +) + +func main() { + ctx := context.Background() + + // Load configuration + cfg, err := config.LoadConfig(os.Getenv("REDIS_ENDPOINTS_CONFIG_PATH")) + if err != nil { + log.Fatalf("Failed to load config: %v", err) + } + + // Create a managed identity credentials provider for system-assigned identity + cp, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedIdentityCredentialsProviderOptions{ + ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ + // For system-assigned identity, we don't need to specify ClientID + Scopes: cfg.GetRedisScopes(), + ManagedIdentityType: "SystemAssigned", + }, + }) + if err != nil { + log.Fatalf("Failed to create credentials provider: %v", err) + } + + // Create Redis client with streaming credentials provider + redisClient := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: []string{cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]}, + StreamingCredentialsProvider: cp, + }) + + // Create second Redis client for cluster + clusterClient := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: cfg.Endpoints["cluster-entraid-acl"].Endpoints, + StreamingCredentialsProvider: cp, + }) + + // Test the connection + pong, err := redisClient.Ping(ctx).Result() + if err != nil { + log.Fatalf("Failed to ping Redis: %v", err) + } + fmt.Printf("Successfully connected to Redis standalone: %s\n", pong) + + // Test cluster connection + clusterPong, err := clusterClient.Ping(ctx).Result() + if err != nil { + log.Fatalf("Failed to ping Redis cluster: %v", err) + } + fmt.Printf("Successfully connected to Redis cluster: %s\n", clusterPong) + + // Set a test key + err = redisClient.Set(ctx, "test-key", "test-value", 0).Err() + if err != nil { + log.Fatalf("Failed to set test key: %v", err) + } + + // Get the test key + val, err := redisClient.Get(ctx, "test-key").Result() + if err != nil { + log.Fatalf("Failed to get test key: %v", err) + } + fmt.Printf("Retrieved value from standalone: %s\n", val) + + // Set a test key in cluster + err = clusterClient.Set(ctx, "test-key", "test-value", 0).Err() + if err != nil { + log.Fatalf("Failed to set test key in cluster: %v", err) + } + + // Get the test key from cluster + clusterVal, err := clusterClient.Get(ctx, "test-key").Result() + if err != nil { + log.Fatalf("Failed to get test key from cluster: %v", err) + } + fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) +} diff --git a/examples/entraid/managedidentity_user/go.mod b/examples/entraid/managedidentity_user/go.mod new file mode 100644 index 0000000..67460b2 --- /dev/null +++ b/examples/entraid/managedidentity_user/go.mod @@ -0,0 +1,32 @@ +module managedidentity_user + +go 1.23.4 + +require ( + config v0.0.0 + github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 + github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b +) + +replace ( + config => ../config + github.com/redis-developer/go-redis-entraid => ../../../ + github.com/redis/go-redis/v9 => github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b +) + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect +) diff --git a/examples/entraid/managedidentity_user/go.sum b/examples/entraid/managedidentity_user/go.sum new file mode 100644 index 0000000..99724cd --- /dev/null +++ b/examples/entraid/managedidentity_user/go.sum @@ -0,0 +1,53 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 h1:iw4+KCeCoieuKodp1d5YhAa1TU/GgogCbw8RbGvsfLA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1/go.mod h1:AP8cDnDTGIVvayqKAhwzpcAyTJosXpvLYNmVFJb98x8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3 h1:BAUsn6/icUFtvUalVwCO0+hSF7qgU9DwwcEfCvtILtw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.3/go.mod h1:QlAsNp4gk9zLD2wiZIvIuv699ynpZ2Tq2ZBp+6MrSEw= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1 h1:8BKxhZZLX/WosEeoCvWysmKUscfa9v8LIPEEU0JjE2o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 h1:l/sz658wqg5ZxqT1cSrmTxGAEXVoBpVOjsZUgMHSJYw= +github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07/go.mod h1:4DrBBopECIq9LRo1hok3rgXUC4AGBhnZiz0Rea2tikc= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/entraid/managedidentity_user/main.go b/examples/entraid/managedidentity_user/main.go new file mode 100644 index 0000000..079df24 --- /dev/null +++ b/examples/entraid/managedidentity_user/main.go @@ -0,0 +1,91 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + + "config" + + entraid "github.com/redis-developer/go-redis-entraid" + "github.com/redis-developer/go-redis-entraid/identity" + "github.com/redis/go-redis/v9" +) + +func main() { + ctx := context.Background() + + // Load configuration + cfg, err := config.LoadConfig(os.Getenv("REDIS_ENDPOINTS_CONFIG_PATH")) + if err != nil { + log.Fatalf("Failed to load config: %v", err) + } + + // Create a managed identity credentials provider for user-assigned identity + cp, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedIdentityCredentialsProviderOptions{ + CredentialsProviderOptions: entraid.CredentialsProviderOptions{ + ClientID: cfg.AzureClientID, + }, + ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ + ManagedIdentityType: "UserAssigned", + UserAssignedClientID: cfg.AzureUserAssignedManagedID, + Scopes: cfg.GetRedisScopes(), + }, + }) + if err != nil { + log.Fatalf("Failed to create credentials provider: %v", err) + } + + // Create Redis client with streaming credentials provider + redisClient := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: []string{cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]}, + StreamingCredentialsProvider: cp, + }) + + // Create second Redis client for cluster + clusterClient := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: cfg.Endpoints["cluster-entraid-acl"].Endpoints, + StreamingCredentialsProvider: cp, + }) + + // Test the connection + pong, err := redisClient.Ping(ctx).Result() + if err != nil { + log.Fatalf("Failed to ping Redis: %v", err) + } + fmt.Printf("Successfully connected to Redis standalone: %s\n", pong) + + // Test cluster connection + clusterPong, err := clusterClient.Ping(ctx).Result() + if err != nil { + log.Fatalf("Failed to ping Redis cluster: %v", err) + } + fmt.Printf("Successfully connected to Redis cluster: %s\n", clusterPong) + + // Set a test key + err = redisClient.Set(ctx, "test-key", "test-value", 0).Err() + if err != nil { + log.Fatalf("Failed to set test key: %v", err) + } + + // Get the test key + val, err := redisClient.Get(ctx, "test-key").Result() + if err != nil { + log.Fatalf("Failed to get test key: %v", err) + } + fmt.Printf("Retrieved value from standalone: %s\n", val) + + // Set a test key in cluster + err = clusterClient.Set(ctx, "test-key", "test-value", 0).Err() + if err != nil { + log.Fatalf("Failed to set test key in cluster: %v", err) + } + + // Get the test key from cluster + clusterVal, err := clusterClient.Get(ctx, "test-key").Result() + if err != nil { + log.Fatalf("Failed to get test key from cluster: %v", err) + } + fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) +} diff --git a/examples/entraid/run_examples.sh b/examples/entraid/run_examples.sh new file mode 100755 index 0000000..06e8dd8 --- /dev/null +++ b/examples/entraid/run_examples.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Env should be set by the executor of the script +# Those examples are configured and executed in a private enviroment +# to verify the entraid intragration is working as expected. +# Common environment vddkariables +#export AZURE_REDIS_SCOPES="https://redis.azure.com/.default" +#export REDIS_ENDPOINVkTS_CONFIG_PATH="endpoints.json" + +# Function to run an example +run_example() { + echo "Running $1 example..." + cd "$1" + go mod tidy + go run main.go + cd .. + echo "----------------------------------------" +} + +# Client Secret example +#export AZURE_CLIENT_ID="your-client-id" +#export AZURE_CLIENT_SECRET="your-client-secret" +#export AZURE_TENANT_ID="your-tenant-id" +run_example "clientsecret" + +# Client Certificate example +#export AZURE_CERT="your-certificate" +#export AZURE_PRIVATE_KEY="your-private-key" +run_example "clientcert" + +# Managed Identity example +#export AZURE_USER_ASSIGNED_MANAGED_ID="your-managed-identity-id" # Optional + +# Run all examples +echo "Running all examples..." + +# Run client secret example +echo "Running client secret example..." +go run clientsecret/main.go + +# Run client certificate example +echo "Running client certificate example..." +go run clientcert/main.go + +# Run managed identity examples +echo "Running managed identity examples..." + +# System-assigned managed identity +echo "Running system-assigned managed identity example..." +go run managedidentity_system/main.go + +# User-assigned managed identity +echo "Running user-assigned managed identity example..." +go run managedidentity_user/main.go + +# Run interactive browser example +echo "Running interactive browser example..." +go run interactive/main.go + +echo "All examples completed!" \ No newline at end of file diff --git a/examples/managed_identity/main.go b/examples/managed_identity/main.go deleted file mode 100644 index 833d791..0000000 --- a/examples/managed_identity/main.go +++ /dev/null @@ -1,55 +0,0 @@ -package main - -import ( - "context" - "fmt" - - entraid "github.com/redis-developer/go-redis-entraid" - "github.com/redis-developer/go-redis-entraid/identity" - redis "github.com/redis/go-redis/v9" -) - -func main() { - ctx := context.Background() - - // Example 1: System-assigned managed identity - // This is the simplest configuration, as it uses the system-assigned identity - // automatically managed by Azure - systemAssignedCP, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedIdentityCredentialsProviderOptions{ - ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ - ManagedIdentityType: identity.SystemAssignedIdentity, - Scopes: []string{"https://redis.azure.com/.default"}, - }, - }) - if err != nil { - panic(fmt.Errorf("failed to create system-assigned managed identity credentials provider: %w", err)) - } - - // Example 2: User-assigned managed identity - // Uncomment and use this example if you want to use a user-assigned managed identity - /* - userAssignedCP, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedIdentityCredentialsProviderOptions{ - ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ - ManagedIdentityType: identity.UserAssignedIdentity, - UserAssignedClientID: "your-user-assigned-identity-client-id", - Scopes: []string{"https://redis.azure.com/.default"}, - }, - }) - if err != nil { - panic(fmt.Errorf("failed to create user-assigned managed identity credentials provider: %w", err)) - } - */ - - // Create Redis client with the credentials provider - redisClient := redis.NewClient(&redis.Options{ - Addr: "your-redis-host:6379", - StreamingCredentialsProvider: systemAssignedCP, // Change to userAssignedCP if using user-assigned identity - }) - - // Test the connection - ok, err := redisClient.Ping(ctx).Result() - if err != nil { - panic(fmt.Errorf("failed to ping Redis: %w", err)) - } - fmt.Println("Ping result:", ok) -} diff --git a/go.mod b/go.mod index b59f728..cf6d791 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0-beta.1 - github.com/redis/go-redis/v9 v9.5.3-0.20250416091253-d0a8c76d8420 + github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b github.com/stretchr/testify v1.10.0 ) diff --git a/go.sum b/go.sum index 0d49fab..e40d107 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.5.3-0.20250416091253-d0a8c76d8420 h1:/dxO9rhmlhKP5pyI7omDH3QQzC0AppWxHT1w5TBsdTU= github.com/redis/go-redis/v9 v9.5.3-0.20250416091253-d0a8c76d8420/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= From 162f6eab9ff2aa2572f7aec5a13c63e653c34933 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Mon, 19 May 2025 18:17:59 +0300 Subject: [PATCH 06/17] fix(examples): fix run script --- examples/entraid/clientcert/go.sum | 2 - examples/entraid/clientsecret/go.sum | 2 - examples/entraid/defaultcredentials/go.sum | 3 +- .../entraid/managedidentity_system/go.sum | 2 - examples/entraid/managedidentity_user/go.sum | 2 - examples/entraid/run_examples.sh | 93 ++++++++++--------- examples/entraid/runscript_test/main.go | 7 ++ go.sum | 2 - 8 files changed, 58 insertions(+), 55 deletions(-) create mode 100644 examples/entraid/runscript_test/main.go diff --git a/examples/entraid/clientcert/go.sum b/examples/entraid/clientcert/go.sum index 99724cd..915d56f 100644 --- a/examples/entraid/clientcert/go.sum +++ b/examples/entraid/clientcert/go.sum @@ -32,8 +32,6 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmd github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 h1:l/sz658wqg5ZxqT1cSrmTxGAEXVoBpVOjsZUgMHSJYw= -github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07/go.mod h1:4DrBBopECIq9LRo1hok3rgXUC4AGBhnZiz0Rea2tikc= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= diff --git a/examples/entraid/clientsecret/go.sum b/examples/entraid/clientsecret/go.sum index 99724cd..915d56f 100644 --- a/examples/entraid/clientsecret/go.sum +++ b/examples/entraid/clientsecret/go.sum @@ -32,8 +32,6 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmd github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 h1:l/sz658wqg5ZxqT1cSrmTxGAEXVoBpVOjsZUgMHSJYw= -github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07/go.mod h1:4DrBBopECIq9LRo1hok3rgXUC4AGBhnZiz0Rea2tikc= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= diff --git a/examples/entraid/defaultcredentials/go.sum b/examples/entraid/defaultcredentials/go.sum index 3b7d2aa..915d56f 100644 --- a/examples/entraid/defaultcredentials/go.sum +++ b/examples/entraid/defaultcredentials/go.sum @@ -32,8 +32,7 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmd github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 h1:l/sz658wqg5ZxqT1cSrmTxGAEXVoBpVOjsZUgMHSJYw= -github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07/go.mod h1:4DrBBopECIq9LRo1hok3rgXUC4AGBhnZiz0Rea2tikc= +github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= diff --git a/examples/entraid/managedidentity_system/go.sum b/examples/entraid/managedidentity_system/go.sum index 99724cd..915d56f 100644 --- a/examples/entraid/managedidentity_system/go.sum +++ b/examples/entraid/managedidentity_system/go.sum @@ -32,8 +32,6 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmd github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 h1:l/sz658wqg5ZxqT1cSrmTxGAEXVoBpVOjsZUgMHSJYw= -github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07/go.mod h1:4DrBBopECIq9LRo1hok3rgXUC4AGBhnZiz0Rea2tikc= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= diff --git a/examples/entraid/managedidentity_user/go.sum b/examples/entraid/managedidentity_user/go.sum index 99724cd..915d56f 100644 --- a/examples/entraid/managedidentity_user/go.sum +++ b/examples/entraid/managedidentity_user/go.sum @@ -32,8 +32,6 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmd github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 h1:l/sz658wqg5ZxqT1cSrmTxGAEXVoBpVOjsZUgMHSJYw= -github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07/go.mod h1:4DrBBopECIq9LRo1hok3rgXUC4AGBhnZiz0Rea2tikc= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= diff --git a/examples/entraid/run_examples.sh b/examples/entraid/run_examples.sh index 06e8dd8..fbfb985 100755 --- a/examples/entraid/run_examples.sh +++ b/examples/entraid/run_examples.sh @@ -6,54 +6,61 @@ #export AZURE_REDIS_SCOPES="https://redis.azure.com/.default" #export REDIS_ENDPOINVkTS_CONFIG_PATH="endpoints.json" +# Exit on any error +set -e + # Function to run an example run_example() { - echo "Running $1 example..." - cd "$1" + local example_dir=$1 + echo "Running $example_dir example..." + + if [ ! -d "$example_dir" ]; then + echo "Error: Directory $example_dir does not exist" + return 1 + fi + + if [ ! -f "$example_dir/main.go" ]; then + echo "Error: main.go not found in $example_dir" + return 1 + fi + + pushd "$example_dir" > /dev/null go mod tidy - go run main.go - cd .. + if ! go run main.go; then + echo "Error: $example_dir example failed" + popd > /dev/null + return 1 + fi + popd > /dev/null echo "----------------------------------------" + return 0 } -# Client Secret example -#export AZURE_CLIENT_ID="your-client-id" -#export AZURE_CLIENT_SECRET="your-client-secret" -#export AZURE_TENANT_ID="your-tenant-id" -run_example "clientsecret" - -# Client Certificate example -#export AZURE_CERT="your-certificate" -#export AZURE_PRIVATE_KEY="your-private-key" -run_example "clientcert" - -# Managed Identity example -#export AZURE_USER_ASSIGNED_MANAGED_ID="your-managed-identity-id" # Optional - -# Run all examples -echo "Running all examples..." - -# Run client secret example -echo "Running client secret example..." -go run clientsecret/main.go - -# Run client certificate example -echo "Running client certificate example..." -go run clientcert/main.go - -# Run managed identity examples -echo "Running managed identity examples..." - -# System-assigned managed identity -echo "Running system-assigned managed identity example..." -go run managedidentity_system/main.go - -# User-assigned managed identity -echo "Running user-assigned managed identity example..." -go run managedidentity_user/main.go +# Track overall success +failed_examples=() -# Run interactive browser example -echo "Running interactive browser example..." -go run interactive/main.go +# Run all examples in the directory +for example in */; do + # Skip config directory as it's not an example + if [ "$example" = "config/" ]; then + continue + fi + + # Remove trailing slash + example=${example%/} + + if ! run_example "$example"; then + failed_examples+=("$example") + fi +done -echo "All examples completed!" \ No newline at end of file +# Report results +echo "----------------------------------------" +if [ ${#failed_examples[@]} -eq 0 ]; then + echo "All examples completed successfully!" + exit 0 +else + echo "The following examples failed:" + printf '%s\n' "${failed_examples[@]}" + exit 1 +fi diff --git a/examples/entraid/runscript_test/main.go b/examples/entraid/runscript_test/main.go new file mode 100644 index 0000000..c06f485 --- /dev/null +++ b/examples/entraid/runscript_test/main.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("OK") +} diff --git a/go.sum b/go.sum index e40d107..fe7563f 100644 --- a/go.sum +++ b/go.sum @@ -29,8 +29,6 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmd github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis/go-redis/v9 v9.5.3-0.20250416091253-d0a8c76d8420 h1:/dxO9rhmlhKP5pyI7omDH3QQzC0AppWxHT1w5TBsdTU= -github.com/redis/go-redis/v9 v9.5.3-0.20250416091253-d0a8c76d8420/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b h1:I6Y+sXfQLIUo8vkx+EcuTcAcs0ZnPceNe8cdQ0HsjQI= github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= From e159e0e1c6c1fd8a61401e48819bc370a6533f16 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Tue, 20 May 2025 13:50:09 +0300 Subject: [PATCH 07/17] fix(tests): fix client configuration --- examples/entraid/clientcert/main.go | 16 ++++--- examples/entraid/clientsecret/main.go | 17 ++++--- examples/entraid/config/config.go | 6 ++- examples/entraid/defaultcredentials/main.go | 45 ++++++++++++++++--- .../entraid/managedidentity_system/main.go | 16 ++++--- examples/entraid/managedidentity_user/main.go | 16 ++++--- 6 files changed, 88 insertions(+), 28 deletions(-) diff --git a/examples/entraid/clientcert/main.go b/examples/entraid/clientcert/main.go index 6e50485..a58ddcf 100644 --- a/examples/entraid/clientcert/main.go +++ b/examples/entraid/clientcert/main.go @@ -44,14 +44,20 @@ func main() { } // Create Redis client with streaming credentials provider - redisClient := redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: []string{cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]}, - StreamingCredentialsProvider: cp, - }) + opts, err := redis.ParseURL(cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]) + if err != nil { + log.Fatalf("Failed to parse Redis URL: %v", err) + } + opts.StreamingCredentialsProvider = cp + redisClient := redis.NewClient(opts) // Create second Redis client for cluster + clusterOpts, err := redis.ParseURL(cfg.Endpoints["cluster-entraid-acl"].Endpoints[0]) + if err != nil { + log.Fatalf("Failed to parse Redis URL: %v", err) + } clusterClient := redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: cfg.Endpoints["cluster-entraid-acl"].Endpoints, + Addrs: []string{clusterOpts.Addr}, StreamingCredentialsProvider: cp, }) diff --git a/examples/entraid/clientsecret/main.go b/examples/entraid/clientsecret/main.go index 4b4f21c..a9cf7f4 100644 --- a/examples/entraid/clientsecret/main.go +++ b/examples/entraid/clientsecret/main.go @@ -41,17 +41,24 @@ func main() { } // Create Redis client with streaming credentials provider - redisClient := redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: []string{cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]}, - StreamingCredentialsProvider: cp, - }) + opts, err := redis.ParseURL(cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]) + if err != nil { + log.Fatalf("Failed to parse Redis URL: %v", err) + } + opts.StreamingCredentialsProvider = cp + redisClient := redis.NewClient(opts) // Create second Redis client for cluster + clusterOpts, err := redis.ParseURL(cfg.Endpoints["cluster-entraid-acl"].Endpoints[0]) + if err != nil { + log.Fatalf("Failed to parse Redis URL: %v", err) + } clusterClient := redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: cfg.Endpoints["cluster-entraid-acl"].Endpoints, + Addrs: []string{clusterOpts.Addr}, StreamingCredentialsProvider: cp, }) + // Test the connection pong, err := redisClient.Ping(ctx).Result() if err != nil { diff --git a/examples/entraid/config/config.go b/examples/entraid/config/config.go index 5ce91bc..1433907 100644 --- a/examples/entraid/config/config.go +++ b/examples/entraid/config/config.go @@ -43,10 +43,14 @@ func LoadConfig(configPath string) (*EntraidConfig, error) { } file, err := os.Open(configPath) + if err != nil { + file, err = os.Open("endpoints.json") + } + if err == nil { defer file.Close() decoder := json.NewDecoder(file) - err = decoder.Decode(config) + err = decoder.Decode(&config.Endpoints) if err != nil { return nil, err } diff --git a/examples/entraid/defaultcredentials/main.go b/examples/entraid/defaultcredentials/main.go index 9d56cf0..1e2fff8 100644 --- a/examples/entraid/defaultcredentials/main.go +++ b/examples/entraid/defaultcredentials/main.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log" + "os" "config" @@ -16,7 +17,7 @@ func main() { ctx := context.Background() // Load configuration - cfg, err := config.LoadConfig("") + cfg, err := config.LoadConfig(os.Getenv("REDIS_ENDPOINTS_CONFIG_PATH")) if err != nil { log.Fatalf("Failed to load config: %v", err) } @@ -37,18 +38,35 @@ func main() { } // Create Redis client with streaming credentials provider - redisClient := redis.NewClusterClient(&redis.ClusterOptions{ - DisableIdentity: true, - Addrs: []string{cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]}, + opts, err := redis.ParseURL(cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]) + if err != nil { + log.Fatalf("Failed to parse Redis URL: %v", err) + } + opts.StreamingCredentialsProvider = cp + redisClient := redis.NewClient(opts) + + // Create second Redis client for cluster + clusterOpts, err := redis.ParseURL(cfg.Endpoints["cluster-entraid-acl"].Endpoints[0]) + if err != nil { + log.Fatalf("Failed to parse Redis URL: %v", err) + } + clusterClient := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: []string{clusterOpts.Addr}, StreamingCredentialsProvider: cp, }) - // Test the connection pong, err := redisClient.Ping(ctx).Result() if err != nil { log.Fatalf("Failed to ping Redis: %v", err) } - fmt.Printf("Successfully connected to Redis: %s\n", pong) + fmt.Printf("Successfully connected to Redis standalone: %s\n", pong) + + // Test cluster connection + clusterPong, err := clusterClient.Ping(ctx).Result() + if err != nil { + log.Fatalf("Failed to ping Redis cluster: %v", err) + } + fmt.Printf("Successfully connected to Redis cluster: %s\n", clusterPong) // Set a test key err = redisClient.Set(ctx, "test-key", "test-value", 0).Err() @@ -61,5 +79,18 @@ func main() { if err != nil { log.Fatalf("Failed to get test key: %v", err) } - fmt.Printf("Retrieved value: %s\n", val) + fmt.Printf("Retrieved value from standalone: %s\n", val) + + // Set a test key in cluster + err = clusterClient.Set(ctx, "test-key", "test-value", 0).Err() + if err != nil { + log.Fatalf("Failed to set test key in cluster: %v", err) + } + + // Get the test key from cluster + clusterVal, err := clusterClient.Get(ctx, "test-key").Result() + if err != nil { + log.Fatalf("Failed to get test key from cluster: %v", err) + } + fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) } diff --git a/examples/entraid/managedidentity_system/main.go b/examples/entraid/managedidentity_system/main.go index e0d1e58..207897d 100644 --- a/examples/entraid/managedidentity_system/main.go +++ b/examples/entraid/managedidentity_system/main.go @@ -35,14 +35,20 @@ func main() { } // Create Redis client with streaming credentials provider - redisClient := redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: []string{cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]}, - StreamingCredentialsProvider: cp, - }) + opts, err := redis.ParseURL(cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]) + if err != nil { + log.Fatalf("Failed to parse Redis URL: %v", err) + } + opts.StreamingCredentialsProvider = cp + redisClient := redis.NewClient(opts) // Create second Redis client for cluster + clusterOpts, err := redis.ParseURL(cfg.Endpoints["cluster-entraid-acl"].Endpoints[0]) + if err != nil { + log.Fatalf("Failed to parse Redis URL: %v", err) + } clusterClient := redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: cfg.Endpoints["cluster-entraid-acl"].Endpoints, + Addrs: []string{clusterOpts.Addr}, StreamingCredentialsProvider: cp, }) diff --git a/examples/entraid/managedidentity_user/main.go b/examples/entraid/managedidentity_user/main.go index 079df24..0bdd101 100644 --- a/examples/entraid/managedidentity_user/main.go +++ b/examples/entraid/managedidentity_user/main.go @@ -38,14 +38,20 @@ func main() { } // Create Redis client with streaming credentials provider - redisClient := redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: []string{cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]}, - StreamingCredentialsProvider: cp, - }) + opts, err := redis.ParseURL(cfg.Endpoints["standalone-entraid-acl"].Endpoints[0]) + if err != nil { + log.Fatalf("Failed to parse Redis URL: %v", err) + } + opts.StreamingCredentialsProvider = cp + redisClient := redis.NewClient(opts) // Create second Redis client for cluster + clusterOpts, err := redis.ParseURL(cfg.Endpoints["cluster-entraid-acl"].Endpoints[0]) + if err != nil { + log.Fatalf("Failed to parse Redis URL: %v", err) + } clusterClient := redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: cfg.Endpoints["cluster-entraid-acl"].Endpoints, + Addrs: []string{clusterOpts.Addr}, StreamingCredentialsProvider: cp, }) From 14962ea4d26c7f1521608d6db3e392a314d098f1 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Tue, 20 May 2025 14:05:32 +0300 Subject: [PATCH 08/17] chore(repo): use new repo under redis org --- README.md | 14 +++++++------- credentials_provider.go | 4 ++-- credentials_provider_test.go | 8 ++++---- entraid.go | 2 +- entraid_test.go | 6 +++--- examples/custom_idp/go.mod | 2 +- examples/custom_idp/go.sum | 4 ++-- examples/custom_idp/main.go | 8 ++++---- examples/default_azure_identity/main.go | 4 ++-- examples/entraid/clientcert/go.mod | 4 ++-- examples/entraid/clientcert/main.go | 4 ++-- examples/entraid/clientsecret/go.mod | 4 ++-- examples/entraid/clientsecret/main.go | 5 ++--- examples/entraid/defaultcredentials/go.mod | 4 ++-- examples/entraid/defaultcredentials/main.go | 4 ++-- examples/entraid/managedidentity_system/go.mod | 4 ++-- examples/entraid/managedidentity_system/main.go | 4 ++-- examples/entraid/managedidentity_user/go.mod | 4 ++-- examples/entraid/managedidentity_user/main.go | 4 ++-- go.mod | 2 +- identity/azure_default_identity_provider.go | 2 +- identity/azure_default_identity_provider_test.go | 2 +- identity/confidential_identity_provider.go | 2 +- identity/confidential_identity_provider_test.go | 2 +- identity/managed_identity_provider.go | 2 +- manager/defaults.go | 4 ++-- manager/entraid_manager.go | 6 +++--- manager/manager_test.go | 4 ++-- manager/token_manager.go | 4 ++-- manager/token_manager_test.go | 4 ++-- providers.go | 6 +++--- providers_test.go | 8 ++++---- shared/identity_provider_response.go | 4 ++-- shared/identity_provider_response_test.go | 2 +- token_listener.go | 4 ++-- token_listener_test.go | 2 +- 36 files changed, 76 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 7a1c328..f8607a1 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ import ( "os" "strings" - "github.com/redis-developer/go-redis-entraid/entraid" + "github.com/redis/go-redis-entraid/entraid" "github.com/redis/go-redis/v9" ) @@ -97,7 +97,7 @@ export AZURE_AUTHORITY_HOST="https://login.microsoftonline.com" # For custom au ### Running the Example ```bash go mod init your-app -go get github.com/redis-developer/go-redis-entraid +go get github.com/redis/go-redis-entraid go run main.go ``` @@ -498,10 +498,10 @@ import ( "strings" "time" - "github.com/redis-developer/go-redis-entraid/entraid" - "github.com/redis-developer/go-redis-entraid/entraid/identity" - "github.com/redis-developer/go-redis-entraid/entraid/manager" - "github.com/redis-developer/go-redis-entraid/entraid/shared" + "github.com/redis/go-redis-entraid/entraid" + "github.com/redis/go-redis-entraid/entraid/identity" + "github.com/redis/go-redis-entraid/entraid/manager" + "github.com/redis/go-redis-entraid/entraid/shared" "github.com/redis/go-redis/v9" ) @@ -870,7 +870,7 @@ The library provides several error types that you can check against: ```go // Import the shared package to access error types -import "github.com/redis-developer/go-redis-entraid/shared" +import "github.com/redis/go-redis-entraid/shared" // Available error types: var ( diff --git a/credentials_provider.go b/credentials_provider.go index 0cd86bc..34839b5 100644 --- a/credentials_provider.go +++ b/credentials_provider.go @@ -7,8 +7,8 @@ import ( "fmt" "sync" - "github.com/redis-developer/go-redis-entraid/manager" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/manager" + "github.com/redis/go-redis-entraid/token" "github.com/redis/go-redis/v9/auth" ) diff --git a/credentials_provider_test.go b/credentials_provider_test.go index d9bfb3f..a63826c 100644 --- a/credentials_provider_test.go +++ b/credentials_provider_test.go @@ -5,10 +5,10 @@ import ( "testing" "time" - "github.com/redis-developer/go-redis-entraid/identity" - "github.com/redis-developer/go-redis-entraid/manager" - "github.com/redis-developer/go-redis-entraid/shared" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/identity" + "github.com/redis/go-redis-entraid/manager" + "github.com/redis/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/token" "github.com/redis/go-redis/v9/auth" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" diff --git a/entraid.go b/entraid.go index 06896c5..6eb0625 100644 --- a/entraid.go +++ b/entraid.go @@ -1,6 +1,6 @@ package entraid -import "github.com/redis-developer/go-redis-entraid/shared" +import "github.com/redis/go-redis-entraid/shared" // IdentityProvider is an alias for the shared.IdentityProvider interface. type IdentityProvider = shared.IdentityProvider diff --git a/entraid_test.go b/entraid_test.go index a824e29..88a3127 100644 --- a/entraid_test.go +++ b/entraid_test.go @@ -7,9 +7,9 @@ import ( "testing" "time" - "github.com/redis-developer/go-redis-entraid/manager" - "github.com/redis-developer/go-redis-entraid/shared" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/manager" + "github.com/redis/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/token" "github.com/redis/go-redis/v9/auth" "github.com/stretchr/testify/mock" ) diff --git a/examples/custom_idp/go.mod b/examples/custom_idp/go.mod index 05f6098..32369ca 100644 --- a/examples/custom_idp/go.mod +++ b/examples/custom_idp/go.mod @@ -3,7 +3,7 @@ module custom_example go 1.23.4 require ( - github.com/redis-developer/go-redis-entraid v0.0.0-20250415111332-9d087bc29c12 + github.com/redis/go-redis-entraid v0.0.0-20250415111332-9d087bc29c12 github.com/redis/go-redis/v9 v9.5.3-0.20250415103233-40a89c56cc52 ) diff --git a/examples/custom_idp/go.sum b/examples/custom_idp/go.sum index 46a0b34..0ee2c1d 100644 --- a/examples/custom_idp/go.sum +++ b/examples/custom_idp/go.sum @@ -32,8 +32,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmd github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis-developer/go-redis-entraid v0.0.0-20250415111332-9d087bc29c12 h1:H5ZfgueBAxs2eAvXtCMEbT2/fLQz/wxW5Ds4c0uzl50= -github.com/redis-developer/go-redis-entraid v0.0.0-20250415111332-9d087bc29c12/go.mod h1:uXKLxCMUAu1VKgWdt8gWc4PWCygiL2pAI5XpnRSVc0w= +github.com/redis/go-redis-entraid v0.0.0-20250415111332-9d087bc29c12 h1:H5ZfgueBAxs2eAvXtCMEbT2/fLQz/wxW5Ds4c0uzl50= +github.com/redis/go-redis-entraid v0.0.0-20250415111332-9d087bc29c12/go.mod h1:uXKLxCMUAu1VKgWdt8gWc4PWCygiL2pAI5XpnRSVc0w= github.com/redis/go-redis/v9 v9.5.3-0.20250415103233-40a89c56cc52 h1:jRx2gINoJsGKxi/RYXCq1VneAAYes9JxUp13xH2oU2g= github.com/redis/go-redis/v9 v9.5.3-0.20250415103233-40a89c56cc52/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= diff --git a/examples/custom_idp/main.go b/examples/custom_idp/main.go index c6c6d58..e4e4f14 100644 --- a/examples/custom_idp/main.go +++ b/examples/custom_idp/main.go @@ -7,10 +7,10 @@ import ( "strings" "time" - entraid "github.com/redis-developer/go-redis-entraid" - "github.com/redis-developer/go-redis-entraid/manager" - "github.com/redis-developer/go-redis-entraid/shared" - "github.com/redis-developer/go-redis-entraid/token" + entraid "github.com/redis/go-redis-entraid" + "github.com/redis/go-redis-entraid/manager" + "github.com/redis/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/token" redis "github.com/redis/go-redis/v9" ) diff --git a/examples/default_azure_identity/main.go b/examples/default_azure_identity/main.go index 4bd1e53..da21373 100644 --- a/examples/default_azure_identity/main.go +++ b/examples/default_azure_identity/main.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - entraid "github.com/redis-developer/go-redis-entraid" - "github.com/redis-developer/go-redis-entraid/identity" + entraid "github.com/redis/go-redis-entraid" + "github.com/redis/go-redis-entraid/identity" redis "github.com/redis/go-redis/v9" ) diff --git a/examples/entraid/clientcert/go.mod b/examples/entraid/clientcert/go.mod index 6fd020f..0e049a9 100644 --- a/examples/entraid/clientcert/go.mod +++ b/examples/entraid/clientcert/go.mod @@ -4,7 +4,7 @@ go 1.23.4 require ( config v0.0.0 - github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 + github.com/redis/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b ) @@ -27,6 +27,6 @@ require ( replace ( config => ../config - github.com/redis-developer/go-redis-entraid => ../../../ + github.com/redis/go-redis-entraid => ../../../ github.com/redis/go-redis/v9 => github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b ) diff --git a/examples/entraid/clientcert/main.go b/examples/entraid/clientcert/main.go index a58ddcf..5ef6bf3 100644 --- a/examples/entraid/clientcert/main.go +++ b/examples/entraid/clientcert/main.go @@ -10,8 +10,8 @@ import ( "config" - entraid "github.com/redis-developer/go-redis-entraid" - "github.com/redis-developer/go-redis-entraid/identity" + entraid "github.com/redis/go-redis-entraid" + "github.com/redis/go-redis-entraid/identity" "github.com/redis/go-redis/v9" ) diff --git a/examples/entraid/clientsecret/go.mod b/examples/entraid/clientsecret/go.mod index 8d86740..7b21a46 100644 --- a/examples/entraid/clientsecret/go.mod +++ b/examples/entraid/clientsecret/go.mod @@ -4,13 +4,13 @@ go 1.23.4 require ( config v0.0.0 - github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 + github.com/redis/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b ) replace ( config => ../config - github.com/redis-developer/go-redis-entraid => ../../../ + github.com/redis/go-redis-entraid => ../../../ github.com/redis/go-redis/v9 => github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b ) diff --git a/examples/entraid/clientsecret/main.go b/examples/entraid/clientsecret/main.go index a9cf7f4..3e570df 100644 --- a/examples/entraid/clientsecret/main.go +++ b/examples/entraid/clientsecret/main.go @@ -8,8 +8,8 @@ import ( "config" - entraid "github.com/redis-developer/go-redis-entraid" - "github.com/redis-developer/go-redis-entraid/identity" + entraid "github.com/redis/go-redis-entraid" + "github.com/redis/go-redis-entraid/identity" "github.com/redis/go-redis/v9" ) @@ -58,7 +58,6 @@ func main() { StreamingCredentialsProvider: cp, }) - // Test the connection pong, err := redisClient.Ping(ctx).Result() if err != nil { diff --git a/examples/entraid/defaultcredentials/go.mod b/examples/entraid/defaultcredentials/go.mod index 4526824..829b73e 100644 --- a/examples/entraid/defaultcredentials/go.mod +++ b/examples/entraid/defaultcredentials/go.mod @@ -4,7 +4,7 @@ go 1.23.4 require ( config v0.0.0 - github.com/redis-developer/go-redis-entraid v0.0.0-00010101000000-000000000000 + github.com/redis/go-redis-entraid v0.0.0-00010101000000-000000000000 github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b ) @@ -27,6 +27,6 @@ require ( replace ( config => ../config - github.com/redis-developer/go-redis-entraid => ../../../ + github.com/redis/go-redis-entraid => ../../../ github.com/redis/go-redis/v9 => github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b ) diff --git a/examples/entraid/defaultcredentials/main.go b/examples/entraid/defaultcredentials/main.go index 1e2fff8..a2f80c7 100644 --- a/examples/entraid/defaultcredentials/main.go +++ b/examples/entraid/defaultcredentials/main.go @@ -8,8 +8,8 @@ import ( "config" - entraid "github.com/redis-developer/go-redis-entraid" - "github.com/redis-developer/go-redis-entraid/identity" + entraid "github.com/redis/go-redis-entraid" + "github.com/redis/go-redis-entraid/identity" "github.com/redis/go-redis/v9" ) diff --git a/examples/entraid/managedidentity_system/go.mod b/examples/entraid/managedidentity_system/go.mod index 8198671..279c6ec 100644 --- a/examples/entraid/managedidentity_system/go.mod +++ b/examples/entraid/managedidentity_system/go.mod @@ -4,13 +4,13 @@ go 1.23.4 require ( config v0.0.0 - github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 + github.com/redis/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b ) replace ( config => ../config - github.com/redis-developer/go-redis-entraid => ../../../ + github.com/redis/go-redis-entraid => ../../../ github.com/redis/go-redis/v9 => github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b ) diff --git a/examples/entraid/managedidentity_system/main.go b/examples/entraid/managedidentity_system/main.go index 207897d..f710cca 100644 --- a/examples/entraid/managedidentity_system/main.go +++ b/examples/entraid/managedidentity_system/main.go @@ -8,8 +8,8 @@ import ( "config" - entraid "github.com/redis-developer/go-redis-entraid" - "github.com/redis-developer/go-redis-entraid/identity" + entraid "github.com/redis/go-redis-entraid" + "github.com/redis/go-redis-entraid/identity" "github.com/redis/go-redis/v9" ) diff --git a/examples/entraid/managedidentity_user/go.mod b/examples/entraid/managedidentity_user/go.mod index 67460b2..847ae27 100644 --- a/examples/entraid/managedidentity_user/go.mod +++ b/examples/entraid/managedidentity_user/go.mod @@ -4,13 +4,13 @@ go 1.23.4 require ( config v0.0.0 - github.com/redis-developer/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 + github.com/redis/go-redis-entraid v0.0.0-20250519132904-1e25b29e9a07 github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b ) replace ( config => ../config - github.com/redis-developer/go-redis-entraid => ../../../ + github.com/redis/go-redis-entraid => ../../../ github.com/redis/go-redis/v9 => github.com/redis/go-redis/v9 v9.5.3-0.20250519143649-1628b87c162b ) diff --git a/examples/entraid/managedidentity_user/main.go b/examples/entraid/managedidentity_user/main.go index 0bdd101..cdf0b4f 100644 --- a/examples/entraid/managedidentity_user/main.go +++ b/examples/entraid/managedidentity_user/main.go @@ -8,8 +8,8 @@ import ( "config" - entraid "github.com/redis-developer/go-redis-entraid" - "github.com/redis-developer/go-redis-entraid/identity" + entraid "github.com/redis/go-redis-entraid" + "github.com/redis/go-redis-entraid/identity" "github.com/redis/go-redis/v9" ) diff --git a/go.mod b/go.mod index cf6d791..c394d2d 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/redis-developer/go-redis-entraid +module github.com/redis/go-redis-entraid go 1.18 diff --git a/identity/azure_default_identity_provider.go b/identity/azure_default_identity_provider.go index 26e6a57..0a73cc5 100644 --- a/identity/azure_default_identity_provider.go +++ b/identity/azure_default_identity_provider.go @@ -7,7 +7,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/redis-developer/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/shared" ) // DefaultAzureIdentityProviderOptions represents the options for the DefaultAzureIdentityProvider. diff --git a/identity/azure_default_identity_provider_test.go b/identity/azure_default_identity_provider_test.go index b73b617..7a2d3dd 100644 --- a/identity/azure_default_identity_provider_test.go +++ b/identity/azure_default_identity_provider_test.go @@ -6,7 +6,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" - "github.com/redis-developer/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/shared" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) diff --git a/identity/confidential_identity_provider.go b/identity/confidential_identity_provider.go index 532b0c8..10f1e0f 100644 --- a/identity/confidential_identity_provider.go +++ b/identity/confidential_identity_provider.go @@ -7,7 +7,7 @@ import ( "fmt" "github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential" - "github.com/redis-developer/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/shared" ) // ConfidentialIdentityProviderOptions represents the options for the confidential identity provider. diff --git a/identity/confidential_identity_provider_test.go b/identity/confidential_identity_provider_test.go index c1adf4f..389263c 100644 --- a/identity/confidential_identity_provider_test.go +++ b/identity/confidential_identity_provider_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential" - "github.com/redis-developer/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/shared" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) diff --git a/identity/managed_identity_provider.go b/identity/managed_identity_provider.go index cb5a4af..9ca3251 100644 --- a/identity/managed_identity_provider.go +++ b/identity/managed_identity_provider.go @@ -7,7 +7,7 @@ import ( mi "github.com/AzureAD/microsoft-authentication-library-for-go/apps/managedidentity" "github.com/AzureAD/microsoft-authentication-library-for-go/apps/public" - "github.com/redis-developer/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/shared" ) // ManagedIdentityClient is an interface that defines the methods for a managed identity client. diff --git a/manager/defaults.go b/manager/defaults.go index 10f4ba5..6b09cf2 100644 --- a/manager/defaults.go +++ b/manager/defaults.go @@ -9,8 +9,8 @@ import ( "time" "github.com/golang-jwt/jwt/v5" - "github.com/redis-developer/go-redis-entraid/shared" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/token" ) const ( diff --git a/manager/entraid_manager.go b/manager/entraid_manager.go index 4b8c716..8a7473e 100644 --- a/manager/entraid_manager.go +++ b/manager/entraid_manager.go @@ -6,9 +6,9 @@ import ( "sync" "time" - "github.com/redis-developer/go-redis-entraid/internal" - "github.com/redis-developer/go-redis-entraid/shared" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/internal" + "github.com/redis/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/token" ) // entraidTokenManager is a struct that implements the TokenManager interface. diff --git a/manager/manager_test.go b/manager/manager_test.go index 8a49969..3f048a9 100644 --- a/manager/manager_test.go +++ b/manager/manager_test.go @@ -9,8 +9,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/AzureAD/microsoft-authentication-library-for-go/apps/public" "github.com/golang-jwt/jwt/v5" - "github.com/redis-developer/go-redis-entraid/shared" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/token" "github.com/stretchr/testify/mock" ) diff --git a/manager/token_manager.go b/manager/token_manager.go index f6c8620..8dcf55c 100644 --- a/manager/token_manager.go +++ b/manager/token_manager.go @@ -5,8 +5,8 @@ import ( "fmt" "time" - "github.com/redis-developer/go-redis-entraid/shared" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/token" ) // TokenManagerOptions is a struct that contains the options for the TokenManager. diff --git a/manager/token_manager_test.go b/manager/token_manager_test.go index 6a0944e..dba0a44 100644 --- a/manager/token_manager_test.go +++ b/manager/token_manager_test.go @@ -16,8 +16,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/AzureAD/microsoft-authentication-library-for-go/apps/public" - "github.com/redis-developer/go-redis-entraid/shared" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/token" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) diff --git a/providers.go b/providers.go index 2d053d7..4f1aebc 100644 --- a/providers.go +++ b/providers.go @@ -3,9 +3,9 @@ package entraid import ( "fmt" - "github.com/redis-developer/go-redis-entraid/identity" - "github.com/redis-developer/go-redis-entraid/manager" - "github.com/redis-developer/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/identity" + "github.com/redis/go-redis-entraid/manager" + "github.com/redis/go-redis-entraid/shared" "github.com/redis/go-redis/v9/auth" ) diff --git a/providers_test.go b/providers_test.go index 604ddac..6716e02 100644 --- a/providers_test.go +++ b/providers_test.go @@ -6,10 +6,10 @@ import ( "testing" "time" - "github.com/redis-developer/go-redis-entraid/identity" - "github.com/redis-developer/go-redis-entraid/manager" - "github.com/redis-developer/go-redis-entraid/shared" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/identity" + "github.com/redis/go-redis-entraid/manager" + "github.com/redis/go-redis-entraid/shared" + "github.com/redis/go-redis-entraid/token" "github.com/redis/go-redis/v9/auth" "github.com/stretchr/testify/assert" ) diff --git a/shared/identity_provider_response.go b/shared/identity_provider_response.go index 86265ec..d60107a 100644 --- a/shared/identity_provider_response.go +++ b/shared/identity_provider_response.go @@ -5,8 +5,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/AzureAD/microsoft-authentication-library-for-go/apps/public" - "github.com/redis-developer/go-redis-entraid/internal" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/internal" + "github.com/redis/go-redis-entraid/token" ) const ( diff --git a/shared/identity_provider_response_test.go b/shared/identity_provider_response_test.go index 084ad09..2227506 100644 --- a/shared/identity_provider_response_test.go +++ b/shared/identity_provider_response_test.go @@ -6,7 +6,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/AzureAD/microsoft-authentication-library-for-go/apps/public" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/token" "github.com/stretchr/testify/assert" ) diff --git a/token_listener.go b/token_listener.go index 8515fda..171aadb 100644 --- a/token_listener.go +++ b/token_listener.go @@ -1,8 +1,8 @@ package entraid import ( - "github.com/redis-developer/go-redis-entraid/manager" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/manager" + "github.com/redis/go-redis-entraid/token" ) // entraidTokenListener implements the TokenListener interface for the entraidCredentialsProvider. diff --git a/token_listener_test.go b/token_listener_test.go index d2d996c..43ebf07 100644 --- a/token_listener_test.go +++ b/token_listener_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/redis-developer/go-redis-entraid/token" + "github.com/redis/go-redis-entraid/token" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) From 9e02923082517688e1ee5884392954833e7de62d Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com> Date: Tue, 20 May 2025 17:42:20 +0300 Subject: [PATCH 09/17] Update examples/entraid/config/config.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- examples/entraid/config/config.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/entraid/config/config.go b/examples/entraid/config/config.go index 1433907..3522f44 100644 --- a/examples/entraid/config/config.go +++ b/examples/entraid/config/config.go @@ -45,17 +45,17 @@ func LoadConfig(configPath string) (*EntraidConfig, error) { file, err := os.Open(configPath) if err != nil { file, err = os.Open("endpoints.json") - } - - if err == nil { - defer file.Close() - decoder := json.NewDecoder(file) - err = decoder.Decode(&config.Endpoints) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to open configuration file: %v", err) } } + defer file.Close() + decoder := json.NewDecoder(file) + err = decoder.Decode(&config.Endpoints) + if err != nil { + return nil, fmt.Errorf("failed to decode configuration file: %v", err) + } // Override with environment variables if they exist if envClientID := os.Getenv("AZURE_CLIENT_ID"); envClientID != "" { config.AzureClientID = envClientID From 9d321e71eae28640556d95468be8ee34d9b1dd84 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Thu, 22 May 2025 12:40:00 +0300 Subject: [PATCH 10/17] fix(examples): fix config imports --- examples/entraid/config/config.go | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/entraid/config/config.go b/examples/entraid/config/config.go index 3522f44..fa3396f 100644 --- a/examples/entraid/config/config.go +++ b/examples/entraid/config/config.go @@ -3,6 +3,7 @@ package config import ( "encoding/json" "os" + "fmt" "strings" ) From 585b7883ddb1a278f275ac346741e477be5988dc Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Thu, 22 May 2025 16:04:15 +0300 Subject: [PATCH 11/17] fix(examples): fix credentials type --- examples/entraid/clientcert/main.go | 2 +- examples/entraid/clientsecret/main.go | 2 +- examples/entraid/config/config.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/entraid/clientcert/main.go b/examples/entraid/clientcert/main.go index 5ef6bf3..e2dd1d5 100644 --- a/examples/entraid/clientcert/main.go +++ b/examples/entraid/clientcert/main.go @@ -29,7 +29,7 @@ func main() { ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ ClientID: cfg.AzureClientID, ClientSecret: cfg.AzureClientSecret, - CredentialsType: "Certificate", + CredentialsType: identity.ClientCertificateCredentialType, Authority: identity.AuthorityConfiguration{ AuthorityType: identity.AuthorityTypeMultiTenant, TenantID: cfg.AzureTenantID, diff --git a/examples/entraid/clientsecret/main.go b/examples/entraid/clientsecret/main.go index 3e570df..de06f24 100644 --- a/examples/entraid/clientsecret/main.go +++ b/examples/entraid/clientsecret/main.go @@ -28,7 +28,7 @@ func main() { ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ ClientID: cfg.AzureClientID, ClientSecret: cfg.AzureClientSecret, - CredentialsType: "ClientSecret", + CredentialsType: identity.ClientSecretCredentialType, Authority: identity.AuthorityConfiguration{ AuthorityType: identity.AuthorityTypeMultiTenant, TenantID: cfg.AzureTenantID, diff --git a/examples/entraid/config/config.go b/examples/entraid/config/config.go index fa3396f..863f6b0 100644 --- a/examples/entraid/config/config.go +++ b/examples/entraid/config/config.go @@ -2,8 +2,8 @@ package config import ( "encoding/json" - "os" "fmt" + "os" "strings" ) From 31f7b951111df53489b6e8f3039510e4452cb2f0 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Fri, 23 May 2025 16:30:07 +0300 Subject: [PATCH 12/17] wip(examples): debug cert example --- examples/entraid/clientcert/main.go | 50 +++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/examples/entraid/clientcert/main.go b/examples/entraid/clientcert/main.go index e2dd1d5..6f52a65 100644 --- a/examples/entraid/clientcert/main.go +++ b/examples/entraid/clientcert/main.go @@ -2,7 +2,9 @@ package main import ( "context" + "crypto/rsa" "crypto/x509" + "encoding/base64" "encoding/pem" "fmt" "log" @@ -21,7 +23,7 @@ func main() { // Load configuration cfg, err := config.LoadConfig(os.Getenv("REDIS_ENDPOINTS_CONFIG_PATH")) if err != nil { - log.Fatalf("Failed to load config: %v", err) + log.Printf("Failed to load config: %v", err) } // Create a confidential identity credentials provider with certificate authentication @@ -36,11 +38,11 @@ func main() { }, Scopes: cfg.GetRedisScopes(), ClientCert: parseCertificates(cfg.AzureCert), - ClientPrivateKey: []byte(cfg.AzurePrivateKey), + ClientPrivateKey: parsePrivateKey(cfg.AzurePrivateKey), }, }) if err != nil { - log.Fatalf("Failed to create credentials provider: %v", err) + log.Printf("Failed to create credentials provider: %v", err) } // Create Redis client with streaming credentials provider @@ -102,21 +104,57 @@ func main() { fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) } +func decodeBase64Pem(pemData string) string { + decoded, err := base64.StdEncoding.DecodeString(pemData) + if err != nil { + log.Fatalf("Failed to decode base64: %v", err) + } + return string(decoded) +} + +func parsePrivateKey(base64data string) *rsa.PrivateKey { + var privateKey *rsa.PrivateKey + var err error + decoded := decodeBase64Pem(base64data) + pk, err := x509.ParsePKCS8PrivateKey([]byte(decoded)) + if err != nil { + log.Printf("Failed to parse pkcs8 key: %v", err) + } + privateKey, _ = pk.(*rsa.PrivateKey) + if privateKey == nil { + pk, err = x509.ParsePKCS1PrivateKey([]byte(decoded)) + if err != nil { + log.Printf("Failed to parse pkcs1 key: %v", err) + } + privateKey, _ = pk.(*rsa.PrivateKey) + } + return privateKey +} + func parseCertificates(pemData string) []*x509.Certificate { var certs []*x509.Certificate + decoded := decodeBase64Pem(pemData) for { - block, rest := pem.Decode([]byte(pemData)) + block, rest := pem.Decode([]byte(decoded)) if block == nil { break } if block.Type == "CERTIFICATE" { cert, err := x509.ParseCertificate(block.Bytes) if err != nil { - log.Fatalf("Failed to parse certificate: %v", err) + log.Printf("Failed to parse certificate: %v", err) } certs = append(certs, cert) } - pemData = string(rest) + decoded = string(rest) + } + if len(certs) == 0 { + decoded := decodeBase64Pem(pemData) + cert, err := x509.ParseCertificate([]byte(decoded)) + if err != nil { + log.Printf("Failed to parse certificate: %v", err) + } + certs = append(certs, cert) } return certs } From c3cd920dab441a65931facf8edab17711aefcd6e Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Fri, 23 May 2025 22:54:19 +0300 Subject: [PATCH 13/17] wip(examples): use object id for user assigned --- README.md | 10 +++---- examples/entraid/managedidentity_user/main.go | 4 +-- identity/managed_identity_provider.go | 28 +++++++++---------- identity/managed_identity_provider_test.go | 10 +++---- identity/providers.go | 5 ++-- identity/providers_test.go | 4 +-- providers_test.go | 16 +++++------ 7 files changed, 39 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index f8607a1..0765d53 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,7 @@ graph TD B -->|Yes| C{System Assigned?} B -->|No| D{Client Credentials?} C -->|Yes| E[SystemAssignedIdentity] - C -->|No| F[UserAssignedIdentity] + C -->|No| F[UserAssignedObjectID] D -->|Yes| G{Client Secret?} D -->|No| H[DefaultAzureIdentity] G -->|Yes| I[ClientSecret] @@ -276,10 +276,10 @@ Options for managed identity authentication: ```go type ManagedIdentityProviderOptions struct { // Required: Type of managed identity - ManagedIdentityType ManagedIdentityType // SystemAssignedIdentity or UserAssignedIdentity + ManagedIdentityType ManagedIdentityType // SystemAssignedIdentity or UserAssignedObjectID // Optional: Client ID for user-assigned identity - UserAssignedClientID string + UserAssignedObjectID string // Optional: Scopes for token access // Default: ["https://redis.azure.com/.default"] @@ -426,8 +426,8 @@ provider, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedId ClientID: os.Getenv("AZURE_CLIENT_ID"), }, ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ - ManagedIdentityType: identity.UserAssignedIdentity, - UserAssignedClientID: os.Getenv("AZURE_USER_ASSIGNED_MANAGED_ID"), + ManagedIdentityType: identity.UserAssignedObjectID, + UserAssignedObjectID: os.Getenv("AZURE_USER_ASSIGNED_MANAGED_ID"), Scopes: []string{"https://redis.azure.com/.default"}, }, }) diff --git a/examples/entraid/managedidentity_user/main.go b/examples/entraid/managedidentity_user/main.go index cdf0b4f..d2babb8 100644 --- a/examples/entraid/managedidentity_user/main.go +++ b/examples/entraid/managedidentity_user/main.go @@ -28,8 +28,8 @@ func main() { ClientID: cfg.AzureClientID, }, ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ - ManagedIdentityType: "UserAssigned", - UserAssignedClientID: cfg.AzureUserAssignedManagedID, + ManagedIdentityType: identity.UserAssignedObjectID, + UserAssignedObjectID: cfg.AzureUserAssignedManagedID, Scopes: cfg.GetRedisScopes(), }, }) diff --git a/identity/managed_identity_provider.go b/identity/managed_identity_provider.go index 9ca3251..f692375 100644 --- a/identity/managed_identity_provider.go +++ b/identity/managed_identity_provider.go @@ -21,11 +21,11 @@ type ManagedIdentityClient interface { // ManagedIdentityProviderOptions represents the options for the managed identity provider. // It is used to configure the identity provider when requesting a token. type ManagedIdentityProviderOptions struct { - // UserAssignedClientID is the client ID of the user assigned identity. + // UserAssignedObjectID is the object ID that is used to identify the user assigned identity. // This is used to identify the identity when requesting a token. - UserAssignedClientID string + UserAssignedObjectID string // ManagedIdentityType is the type of managed identity. - // This can be either SystemAssigned or UserAssigned. + // This can be either SystemAssigned or UserAssignedObjectID. ManagedIdentityType string // Scopes is a list of scopes that the identity has access to. // This is used to specify the permissions that the identity has when requesting a token. @@ -34,12 +34,12 @@ type ManagedIdentityProviderOptions struct { // ManagedIdentityProvider represents a managed identity provider. type ManagedIdentityProvider struct { - // userAssignedClientID is the client ID of the user assigned identity. + // userAssignedObjectID is the client ID of the user assigned identity. // This is used to identify the identity when requesting a token. - userAssignedClientID string + userAssignedObjectID string // managedIdentityType is the type of managed identity. - // This can be either SystemAssigned or UserAssigned. + // This can be either SystemAssigned or UserAssignedObjectID. managedIdentityType string // scopes is a list of scopes that the identity has access to. @@ -64,7 +64,7 @@ func (c *realManagedIdentityClient) AcquireToken(ctx context.Context, resource s func NewManagedIdentityProvider(opts ManagedIdentityProviderOptions) (*ManagedIdentityProvider, error) { var client ManagedIdentityClient - if opts.ManagedIdentityType != SystemAssignedIdentity && opts.ManagedIdentityType != UserAssignedIdentity { + if opts.ManagedIdentityType != SystemAssignedIdentity && opts.ManagedIdentityType != UserAssignedObjectID { return nil, errors.New("invalid managed identity type") } @@ -78,13 +78,13 @@ func NewManagedIdentityProvider(opts ManagedIdentityProviderOptions) (*ManagedId return nil, fmt.Errorf("couldn't create managed identity client: %w", err) } client = &realManagedIdentityClient{client: miClient} - case UserAssignedIdentity: - // UserAssignedIdentity is required to be specified when using a user assigned identity. - if opts.UserAssignedClientID == "" { - return nil, errors.New("user assigned client ID is required when using user assigned identity") + case UserAssignedObjectID: + // UserAssignedObjectID is required to be specified when using a user assigned identity. + if opts.UserAssignedObjectID == "" { + return nil, errors.New("user assigned object ID is required when using user assigned identity") } - // UserAssignedIdentity is the type of identity that is managed by the user. - miClient, err := mi.New(mi.UserAssignedClientID(opts.UserAssignedClientID)) + // UserAssignedObjectID is the type of identity that is managed by the user. + miClient, err := mi.New(mi.UserAssignedObjectID(opts.UserAssignedObjectID)) if err != nil { return nil, fmt.Errorf("couldn't create managed identity client: %w", err) } @@ -92,7 +92,7 @@ func NewManagedIdentityProvider(opts ManagedIdentityProviderOptions) (*ManagedId } return &ManagedIdentityProvider{ - userAssignedClientID: opts.UserAssignedClientID, + userAssignedObjectID: opts.UserAssignedObjectID, managedIdentityType: opts.ManagedIdentityType, scopes: opts.Scopes, client: client, diff --git a/identity/managed_identity_provider_test.go b/identity/managed_identity_provider_test.go index 80dd661..bd42f8f 100644 --- a/identity/managed_identity_provider_test.go +++ b/identity/managed_identity_provider_test.go @@ -39,8 +39,8 @@ func TestNewManagedIdentityProvider(t *testing.T) { { name: "User assigned identity with client ID", opts: ManagedIdentityProviderOptions{ - ManagedIdentityType: UserAssignedIdentity, - UserAssignedClientID: "test-client-id", + ManagedIdentityType: UserAssignedObjectID, + UserAssignedObjectID: "test-client-id", Scopes: []string{"https://redis.azure.com"}, }, expectedError: "", @@ -48,10 +48,10 @@ func TestNewManagedIdentityProvider(t *testing.T) { { name: "User assigned identity without client ID", opts: ManagedIdentityProviderOptions{ - ManagedIdentityType: UserAssignedIdentity, + ManagedIdentityType: UserAssignedObjectID, Scopes: []string{"https://redis.azure.com"}, }, - expectedError: "user assigned client ID is required when using user assigned identity", + expectedError: "user assigned object ID is required when using user assigned identity", }, { name: "Invalid identity type", @@ -75,7 +75,7 @@ func TestNewManagedIdentityProvider(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, provider) assert.Equal(t, tt.opts.ManagedIdentityType, provider.managedIdentityType) - assert.Equal(t, tt.opts.UserAssignedClientID, provider.userAssignedClientID) + assert.Equal(t, tt.opts.UserAssignedObjectID, provider.userAssignedObjectID) assert.Equal(t, tt.opts.Scopes, provider.scopes) assert.NotNil(t, provider.client) } diff --git a/identity/providers.go b/identity/providers.go index 24126f3..6c7fcc3 100644 --- a/identity/providers.go +++ b/identity/providers.go @@ -5,8 +5,9 @@ package identity const ( // SystemAssignedIdentity is the type of identity that is automatically managed by Azure. SystemAssignedIdentity = "SystemAssigned" - // UserAssignedIdentity is the type of identity that is managed by the user. - UserAssignedIdentity = "UserAssigned" + // UserAssignedObjectID is the type of identity that is managed by the user. + UserAssignedObjectID = "UserAssignedObjectID" + // ClientSecretCredentialType is the type of credentials that uses a client secret to authenticate. ClientSecretCredentialType = "ClientSecret" diff --git a/identity/providers_test.go b/identity/providers_test.go index 0712d0f..d217ac7 100644 --- a/identity/providers_test.go +++ b/identity/providers_test.go @@ -16,8 +16,8 @@ func TestConstants(t *testing.T) { expected: "SystemAssigned", }, { - name: "UserAssignedIdentity", - got: UserAssignedIdentity, + name: "UserAssignedObjectID", + got: UserAssignedObjectID, expected: "UserAssigned", }, { diff --git a/providers_test.go b/providers_test.go index 6716e02..b0facab 100644 --- a/providers_test.go +++ b/providers_test.go @@ -30,8 +30,8 @@ func TestNewManagedIdentityCredentialsProvider(t *testing.T) { }, }, ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ - UserAssignedClientID: "test-client-id", - ManagedIdentityType: identity.UserAssignedIdentity, + UserAssignedObjectID: "test-client-id", + ManagedIdentityType: identity.UserAssignedObjectID, Scopes: []string{identity.RedisScopeDefault}, }, }, @@ -277,8 +277,8 @@ func TestCredentialsProviderInterface(t *testing.T) { }, }, ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ - UserAssignedClientID: "test-client-id", - ManagedIdentityType: identity.UserAssignedIdentity, + UserAssignedObjectID: "test-client-id", + ManagedIdentityType: identity.UserAssignedObjectID, Scopes: []string{identity.RedisScopeDefault}, }, } @@ -392,8 +392,8 @@ func TestNewManagedIdentityCredentialsProvider_TokenManagerFactoryError(t *testi }, }, ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ - UserAssignedClientID: "test-client-id", - ManagedIdentityType: identity.UserAssignedIdentity, + UserAssignedObjectID: "test-client-id", + ManagedIdentityType: identity.UserAssignedObjectID, Scopes: []string{identity.RedisScopeDefault}, }, } @@ -470,8 +470,8 @@ func TestNewManagedIdentityCredentialsProvider_TokenManagerStartError(t *testing }, }, ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ - UserAssignedClientID: "test-client-id", - ManagedIdentityType: identity.UserAssignedIdentity, + UserAssignedObjectID: "test-client-id", + ManagedIdentityType: identity.UserAssignedObjectID, Scopes: []string{identity.RedisScopeDefault}, }, } From 33a523d6877952109a7fe3665e57c3936b6106d7 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Fri, 23 May 2025 23:52:58 +0300 Subject: [PATCH 14/17] wip(examples): rename examples and add shorter expirations --- examples/entraid/clientcert/main.go | 37 +++++++++++++++++++ examples/entraid/clientsecret/main.go | 37 +++++++++++++++++++ examples/entraid/defaultcredentials/main.go | 37 +++++++++++++++++++ .../go.mod | 2 +- .../go.sum | 0 .../main.go | 37 +++++++++++++++++++ .../go.mod | 2 +- .../go.sum | 0 .../main.go | 35 ++++++++++++++++++ identity/providers.go | 1 - 10 files changed, 185 insertions(+), 3 deletions(-) rename examples/entraid/{managedidentity_user => managedidentity_systemassigned}/go.mod (96%) rename examples/entraid/{managedidentity_system => managedidentity_systemassigned}/go.sum (100%) rename examples/entraid/{managedidentity_system => managedidentity_systemassigned}/main.go (70%) rename examples/entraid/{managedidentity_system => managedidentity_userassigned}/go.mod (96%) rename examples/entraid/{managedidentity_user => managedidentity_userassigned}/go.sum (100%) rename examples/entraid/{managedidentity_user => managedidentity_userassigned}/main.go (72%) diff --git a/examples/entraid/clientcert/main.go b/examples/entraid/clientcert/main.go index 6f52a65..dff6c30 100644 --- a/examples/entraid/clientcert/main.go +++ b/examples/entraid/clientcert/main.go @@ -9,11 +9,13 @@ import ( "fmt" "log" "os" + "time" "config" entraid "github.com/redis/go-redis-entraid" "github.com/redis/go-redis-entraid/identity" + "github.com/redis/go-redis-entraid/manager" "github.com/redis/go-redis/v9" ) @@ -28,6 +30,12 @@ func main() { // Create a confidential identity credentials provider with certificate authentication cp, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialCredentialsProviderOptions{ + CredentialsProviderOptions: entraid.CredentialsProviderOptions{ + TokenManagerOptions: manager.TokenManagerOptions{ + ExpirationRefreshRatio: 0.001, // Set to refresh very early + LowerRefreshBound: time.Second * 1, // Set lower bound to 1 second + }, + }, ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ ClientID: cfg.AzureClientID, ClientSecret: cfg.AzureClientSecret, @@ -102,6 +110,35 @@ func main() { log.Fatalf("Failed to get test key from cluster: %v", err) } fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) + + // Wait for token to expire + fmt.Println("Waiting for token to expire...") + time.Sleep(3 * time.Second) + + // Test token refresh by retrying operations + fmt.Println("Testing token refresh...") + + // Retry standalone operations + for i := 0; i < 3; i++ { + pong, err = redisClient.Ping(ctx).Result() + if err != nil { + log.Printf("Failed to ping Redis (attempt %d): %v", i+1, err) + continue + } + fmt.Printf("Successfully pinged Redis standalone after token refresh: %s\n", pong) + break + } + + // Retry cluster operations + for i := 0; i < 3; i++ { + clusterPong, err = clusterClient.Ping(ctx).Result() + if err != nil { + log.Printf("Failed to ping Redis cluster (attempt %d): %v", i+1, err) + continue + } + fmt.Printf("Successfully pinged Redis cluster after token refresh: %s\n", clusterPong) + break + } } func decodeBase64Pem(pemData string) string { diff --git a/examples/entraid/clientsecret/main.go b/examples/entraid/clientsecret/main.go index de06f24..4387bad 100644 --- a/examples/entraid/clientsecret/main.go +++ b/examples/entraid/clientsecret/main.go @@ -5,11 +5,13 @@ import ( "fmt" "log" "os" + "time" "config" entraid "github.com/redis/go-redis-entraid" "github.com/redis/go-redis-entraid/identity" + "github.com/redis/go-redis-entraid/manager" "github.com/redis/go-redis/v9" ) @@ -25,6 +27,12 @@ func main() { // Create a confidential identity credentials provider // This example uses client secret authentication cp, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialCredentialsProviderOptions{ + CredentialsProviderOptions: entraid.CredentialsProviderOptions{ + TokenManagerOptions: manager.TokenManagerOptions{ + ExpirationRefreshRatio: 0.001, // Set to refresh very early + LowerRefreshBound: time.Second * 1, // Set lower bound to 1 second + }, + }, ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ ClientID: cfg.AzureClientID, ClientSecret: cfg.AzureClientSecret, @@ -97,4 +105,33 @@ func main() { log.Fatalf("Failed to get test key from cluster: %v", err) } fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) + + // Wait for token to expire + fmt.Println("Waiting for token to expire...") + time.Sleep(3 * time.Second) + + // Test token refresh by retrying operations + fmt.Println("Testing token refresh...") + + // Retry standalone operations + for i := 0; i < 3; i++ { + pong, err = redisClient.Ping(ctx).Result() + if err != nil { + log.Printf("Failed to ping Redis (attempt %d): %v", i+1, err) + continue + } + fmt.Printf("Successfully pinged Redis standalone after token refresh: %s\n", pong) + break + } + + // Retry cluster operations + for i := 0; i < 3; i++ { + clusterPong, err = clusterClient.Ping(ctx).Result() + if err != nil { + log.Printf("Failed to ping Redis cluster (attempt %d): %v", i+1, err) + continue + } + fmt.Printf("Successfully pinged Redis cluster after token refresh: %s\n", clusterPong) + break + } } diff --git a/examples/entraid/defaultcredentials/main.go b/examples/entraid/defaultcredentials/main.go index a2f80c7..ac8d8da 100644 --- a/examples/entraid/defaultcredentials/main.go +++ b/examples/entraid/defaultcredentials/main.go @@ -5,11 +5,13 @@ import ( "fmt" "log" "os" + "time" "config" entraid "github.com/redis/go-redis-entraid" "github.com/redis/go-redis-entraid/identity" + "github.com/redis/go-redis-entraid/manager" "github.com/redis/go-redis/v9" ) @@ -29,6 +31,12 @@ func main() { // 3. Azure CLI credentials // 4. Visual Studio Code credentials cp, err := entraid.NewDefaultAzureCredentialsProvider(entraid.DefaultAzureCredentialsProviderOptions{ + CredentialsProviderOptions: entraid.CredentialsProviderOptions{ + TokenManagerOptions: manager.TokenManagerOptions{ + ExpirationRefreshRatio: 0.001, // Set to refresh very early + LowerRefreshBound: time.Second * 1, // Set lower bound to 1 second + }, + }, DefaultAzureIdentityProviderOptions: identity.DefaultAzureIdentityProviderOptions{ Scopes: []string{"https://redis.azure.com/.default"}, }, @@ -93,4 +101,33 @@ func main() { log.Fatalf("Failed to get test key from cluster: %v", err) } fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) + + // Wait for token to expire + fmt.Println("Waiting for token to expire...") + time.Sleep(3 * time.Second) + + // Test token refresh by retrying operations + fmt.Println("Testing token refresh...") + + // Retry standalone operations + for i := 0; i < 3; i++ { + pong, err = redisClient.Ping(ctx).Result() + if err != nil { + log.Printf("Failed to ping Redis (attempt %d): %v", i+1, err) + continue + } + fmt.Printf("Successfully pinged Redis standalone after token refresh: %s\n", pong) + break + } + + // Retry cluster operations + for i := 0; i < 3; i++ { + clusterPong, err = clusterClient.Ping(ctx).Result() + if err != nil { + log.Printf("Failed to ping Redis cluster (attempt %d): %v", i+1, err) + continue + } + fmt.Printf("Successfully pinged Redis cluster after token refresh: %s\n", clusterPong) + break + } } diff --git a/examples/entraid/managedidentity_user/go.mod b/examples/entraid/managedidentity_systemassigned/go.mod similarity index 96% rename from examples/entraid/managedidentity_user/go.mod rename to examples/entraid/managedidentity_systemassigned/go.mod index 847ae27..15f610c 100644 --- a/examples/entraid/managedidentity_user/go.mod +++ b/examples/entraid/managedidentity_systemassigned/go.mod @@ -1,4 +1,4 @@ -module managedidentity_user +module managedidentity_systemassigned go 1.23.4 diff --git a/examples/entraid/managedidentity_system/go.sum b/examples/entraid/managedidentity_systemassigned/go.sum similarity index 100% rename from examples/entraid/managedidentity_system/go.sum rename to examples/entraid/managedidentity_systemassigned/go.sum diff --git a/examples/entraid/managedidentity_system/main.go b/examples/entraid/managedidentity_systemassigned/main.go similarity index 70% rename from examples/entraid/managedidentity_system/main.go rename to examples/entraid/managedidentity_systemassigned/main.go index f710cca..cf6ef1e 100644 --- a/examples/entraid/managedidentity_system/main.go +++ b/examples/entraid/managedidentity_systemassigned/main.go @@ -5,11 +5,13 @@ import ( "fmt" "log" "os" + "time" "config" entraid "github.com/redis/go-redis-entraid" "github.com/redis/go-redis-entraid/identity" + "github.com/redis/go-redis-entraid/manager" "github.com/redis/go-redis/v9" ) @@ -24,6 +26,12 @@ func main() { // Create a managed identity credentials provider for system-assigned identity cp, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedIdentityCredentialsProviderOptions{ + CredentialsProviderOptions: entraid.CredentialsProviderOptions{ + TokenManagerOptions: manager.TokenManagerOptions{ + ExpirationRefreshRatio: 0.001, // Set to refresh very early + LowerRefreshBound: time.Second * 1, // Set lower bound to 1 second + }, + }, ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ // For system-assigned identity, we don't need to specify ClientID Scopes: cfg.GetRedisScopes(), @@ -91,4 +99,33 @@ func main() { log.Fatalf("Failed to get test key from cluster: %v", err) } fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) + + // Wait for token to expire + fmt.Println("Waiting for token to expire...") + time.Sleep(3 * time.Second) + + // Test token refresh by retrying operations + fmt.Println("Testing token refresh...") + + // Retry standalone operations + for i := 0; i < 3; i++ { + pong, err = redisClient.Ping(ctx).Result() + if err != nil { + log.Printf("Failed to ping Redis (attempt %d): %v", i+1, err) + continue + } + fmt.Printf("Successfully pinged Redis standalone after token refresh: %s\n", pong) + break + } + + // Retry cluster operations + for i := 0; i < 3; i++ { + clusterPong, err = clusterClient.Ping(ctx).Result() + if err != nil { + log.Printf("Failed to ping Redis cluster (attempt %d): %v", i+1, err) + continue + } + fmt.Printf("Successfully pinged Redis cluster after token refresh: %s\n", clusterPong) + break + } } diff --git a/examples/entraid/managedidentity_system/go.mod b/examples/entraid/managedidentity_userassigned/go.mod similarity index 96% rename from examples/entraid/managedidentity_system/go.mod rename to examples/entraid/managedidentity_userassigned/go.mod index 279c6ec..37c884e 100644 --- a/examples/entraid/managedidentity_system/go.mod +++ b/examples/entraid/managedidentity_userassigned/go.mod @@ -1,4 +1,4 @@ -module managedidentity_system +module managedidentity_userassigned go 1.23.4 diff --git a/examples/entraid/managedidentity_user/go.sum b/examples/entraid/managedidentity_userassigned/go.sum similarity index 100% rename from examples/entraid/managedidentity_user/go.sum rename to examples/entraid/managedidentity_userassigned/go.sum diff --git a/examples/entraid/managedidentity_user/main.go b/examples/entraid/managedidentity_userassigned/main.go similarity index 72% rename from examples/entraid/managedidentity_user/main.go rename to examples/entraid/managedidentity_userassigned/main.go index d2babb8..beab7c5 100644 --- a/examples/entraid/managedidentity_user/main.go +++ b/examples/entraid/managedidentity_userassigned/main.go @@ -5,11 +5,13 @@ import ( "fmt" "log" "os" + "time" "config" entraid "github.com/redis/go-redis-entraid" "github.com/redis/go-redis-entraid/identity" + "github.com/redis/go-redis-entraid/manager" "github.com/redis/go-redis/v9" ) @@ -26,6 +28,10 @@ func main() { cp, err := entraid.NewManagedIdentityCredentialsProvider(entraid.ManagedIdentityCredentialsProviderOptions{ CredentialsProviderOptions: entraid.CredentialsProviderOptions{ ClientID: cfg.AzureClientID, + TokenManagerOptions: manager.TokenManagerOptions{ + ExpirationRefreshRatio: 0.001, // Set to refresh very early + LowerRefreshBound: time.Second * 1, // Set lower bound to 1 second + }, }, ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ ManagedIdentityType: identity.UserAssignedObjectID, @@ -94,4 +100,33 @@ func main() { log.Fatalf("Failed to get test key from cluster: %v", err) } fmt.Printf("Retrieved value from cluster: %s\n", clusterVal) + + // Wait for token to expire + fmt.Println("Waiting for token to expire...") + time.Sleep(3 * time.Second) + + // Test token refresh by retrying operations + fmt.Println("Testing token refresh...") + + // Retry standalone operations + for i := 0; i < 3; i++ { + pong, err = redisClient.Ping(ctx).Result() + if err != nil { + log.Printf("Failed to ping Redis (attempt %d): %v", i+1, err) + continue + } + fmt.Printf("Successfully pinged Redis standalone after token refresh: %s\n", pong) + break + } + + // Retry cluster operations + for i := 0; i < 3; i++ { + clusterPong, err = clusterClient.Ping(ctx).Result() + if err != nil { + log.Printf("Failed to ping Redis cluster (attempt %d): %v", i+1, err) + continue + } + fmt.Printf("Successfully pinged Redis cluster after token refresh: %s\n", clusterPong) + break + } } diff --git a/identity/providers.go b/identity/providers.go index 6c7fcc3..946634c 100644 --- a/identity/providers.go +++ b/identity/providers.go @@ -8,7 +8,6 @@ const ( // UserAssignedObjectID is the type of identity that is managed by the user. UserAssignedObjectID = "UserAssignedObjectID" - // ClientSecretCredentialType is the type of credentials that uses a client secret to authenticate. ClientSecretCredentialType = "ClientSecret" // ClientCertificateCredentialType is the type of credentials that uses a client certificate to authenticate. From a0235fb3c1c1a176a68b1f5e3339991354454f6c Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Fri, 23 May 2025 23:55:24 +0300 Subject: [PATCH 15/17] fix(tests): remove examples from coverage trigger ci. --- .testcoverage.yml | 1 + identity/providers_test.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.testcoverage.yml b/.testcoverage.yml index 3c88348..81da8d9 100644 --- a/.testcoverage.yml +++ b/.testcoverage.yml @@ -38,6 +38,7 @@ override: exclude: # Exclude files or packages matching their paths paths: + - ^examples - \.pb\.go$ # excludes all protobuf generated files - ^pkg/bar # exclude package `pkg/bar` diff --git a/identity/providers_test.go b/identity/providers_test.go index d217ac7..a088752 100644 --- a/identity/providers_test.go +++ b/identity/providers_test.go @@ -18,7 +18,7 @@ func TestConstants(t *testing.T) { { name: "UserAssignedObjectID", got: UserAssignedObjectID, - expected: "UserAssigned", + expected: "UserAssignedObjectID", }, { name: "ClientSecretCredentialType", From 78763af5dc7fce5fd8268d2abe0bc758acaa06a8 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Sat, 24 May 2025 00:47:50 +0300 Subject: [PATCH 16/17] test(config): add test for the config parsing in the examples --- examples/entraid/config/config_test.go | 262 +++++++++++++++++++ examples/entraid/runscript_test/main.go | 6 +- examples/entraid/runscript_test/main_test.go | 11 + 3 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 examples/entraid/config/config_test.go create mode 100644 examples/entraid/runscript_test/main_test.go diff --git a/examples/entraid/config/config_test.go b/examples/entraid/config/config_test.go new file mode 100644 index 0000000..a050dbb --- /dev/null +++ b/examples/entraid/config/config_test.go @@ -0,0 +1,262 @@ +package config + +import ( + "os" + "path/filepath" + "testing" +) + +func TestLoadConfig(t *testing.T) { + // Create a temporary directory for test files + tempDir := t.TempDir() + + // Test cases + tests := []struct { + name string + configContent string + envVars map[string]string + expectedConfig *EntraidConfig + expectError bool + configPath string // Add configPath to test different paths + }{ + { + name: "valid config file", + configContent: `{ + "endpoint1": { + "username": "testuser", + "password": "testpass", + "tls": true, + "certificatesLocation": "/path/to/certs", + "endpoints": ["redis1:6379", "redis2:6379"] + } + }`, + expectedConfig: &EntraidConfig{ + Endpoints: map[string]RedisEndpoint{ + "endpoint1": { + Username: "testuser", + Password: "testpass", + TLS: true, + CertificatesLocation: "/path/to/certs", + Endpoints: []string{"redis1:6379", "redis2:6379"}, + }, + }, + }, + expectError: false, + }, + { + name: "invalid JSON", + configContent: `{ + "endpoint1": { + "username": "testuser", + "password": "testpass", + "tls": true, + "certificatesLocation": "/path/to/certs", + "endpoints": ["redis1:6379", "redis2:6379"] + } + `, // Missing closing brace + expectError: true, + }, + { + name: "config with environment variables", + configContent: `{ + "endpoint1": { + "endpoints": ["redis1:6379"] + } + }`, + envVars: map[string]string{ + "AZURE_CLIENT_ID": "test-client-id", + "AZURE_CLIENT_SECRET": "test-client-secret", + "AZURE_TENANT_ID": "test-tenant-id", + "AZURE_AUTHORITY": "test-authority", + "AZURE_REDIS_SCOPES": "scope1,scope2", + }, + expectedConfig: &EntraidConfig{ + Endpoints: map[string]RedisEndpoint{ + "endpoint1": { + Endpoints: []string{"redis1:6379"}, + }, + }, + AzureClientID: "test-client-id", + AzureClientSecret: "test-client-secret", + AzureTenantID: "test-tenant-id", + AzureAuthority: "test-authority", + AzureRedisScopes: "scope1,scope2", + }, + expectError: false, + }, + { + name: "non-existent config file", + configPath: "non_existent.json", + expectError: true, + }, + { + name: "empty config file", + configContent: `{}`, + expectedConfig: &EntraidConfig{ + Endpoints: map[string]RedisEndpoint{}, + }, + expectError: false, + }, + { + name: "config with all Azure environment variables", + configContent: `{ + "endpoint1": { + "endpoints": ["redis1:6379"] + } + }`, + envVars: map[string]string{ + "AZURE_CLIENT_ID": "test-client-id", + "AZURE_CLIENT_SECRET": "test-client-secret", + "AZURE_TENANT_ID": "test-tenant-id", + "AZURE_AUTHORITY": "test-authority", + "AZURE_REDIS_SCOPES": "scope1,scope2", + "AZURE_CERT": "test-cert", + "AZURE_PRIVATE_KEY": "test-key", + "AZURE_USER_ASSIGNED_MANAGED_ID": "test-managed-id", + }, + expectedConfig: &EntraidConfig{ + Endpoints: map[string]RedisEndpoint{ + "endpoint1": { + Endpoints: []string{"redis1:6379"}, + }, + }, + AzureClientID: "test-client-id", + AzureClientSecret: "test-client-secret", + AzureTenantID: "test-tenant-id", + AzureAuthority: "test-authority", + AzureRedisScopes: "scope1,scope2", + AzureCert: "test-cert", + AzurePrivateKey: "test-key", + AzureUserAssignedManagedID: "test-managed-id", + }, + expectError: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create test config file if content is provided + var configPath string + if tt.configContent != "" { + configPath = filepath.Join(tempDir, "endpoints.json") + if err := os.WriteFile(configPath, []byte(tt.configContent), 0644); err != nil { + t.Fatalf("Failed to create test config file: %v", err) + } + } else if tt.configPath != "" { + configPath = tt.configPath + } + + // Set environment variables + for k, v := range tt.envVars { + os.Setenv(k, v) + } + defer func() { + // Clean up environment variables + for k := range tt.envVars { + os.Unsetenv(k) + } + }() + + // Load config + config, err := LoadConfig(configPath) + + // Check error + if tt.expectError { + if err == nil { + t.Error("Expected error but got none") + } + return + } + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + // Verify config + if len(config.Endpoints) != len(tt.expectedConfig.Endpoints) { + t.Errorf("Expected %d endpoints, got %d", len(tt.expectedConfig.Endpoints), len(config.Endpoints)) + } + + // Check environment variables + if tt.expectedConfig.AzureClientID != "" && config.AzureClientID != tt.expectedConfig.AzureClientID { + t.Errorf("Expected AzureClientID %s, got %s", tt.expectedConfig.AzureClientID, config.AzureClientID) + } + if tt.expectedConfig.AzureClientSecret != "" && config.AzureClientSecret != tt.expectedConfig.AzureClientSecret { + t.Errorf("Expected AzureClientSecret %s, got %s", tt.expectedConfig.AzureClientSecret, config.AzureClientSecret) + } + if tt.expectedConfig.AzureTenantID != "" && config.AzureTenantID != tt.expectedConfig.AzureTenantID { + t.Errorf("Expected AzureTenantID %s, got %s", tt.expectedConfig.AzureTenantID, config.AzureTenantID) + } + if tt.expectedConfig.AzureAuthority != "" && config.AzureAuthority != tt.expectedConfig.AzureAuthority { + t.Errorf("Expected AzureAuthority %s, got %s", tt.expectedConfig.AzureAuthority, config.AzureAuthority) + } + if tt.expectedConfig.AzureRedisScopes != "" && config.AzureRedisScopes != tt.expectedConfig.AzureRedisScopes { + t.Errorf("Expected AzureRedisScopes %s, got %s", tt.expectedConfig.AzureRedisScopes, config.AzureRedisScopes) + } + if tt.expectedConfig.AzureCert != "" && config.AzureCert != tt.expectedConfig.AzureCert { + t.Errorf("Expected AzureCert %s, got %s", tt.expectedConfig.AzureCert, config.AzureCert) + } + if tt.expectedConfig.AzurePrivateKey != "" && config.AzurePrivateKey != tt.expectedConfig.AzurePrivateKey { + t.Errorf("Expected AzurePrivateKey %s, got %s", tt.expectedConfig.AzurePrivateKey, config.AzurePrivateKey) + } + if tt.expectedConfig.AzureUserAssignedManagedID != "" && config.AzureUserAssignedManagedID != tt.expectedConfig.AzureUserAssignedManagedID { + t.Errorf("Expected AzureUserAssignedManagedID %s, got %s", tt.expectedConfig.AzureUserAssignedManagedID, config.AzureUserAssignedManagedID) + } + }) + } +} + +func TestGetRedisScopes(t *testing.T) { + tests := []struct { + name string + config *EntraidConfig + expectedScopes []string + }{ + { + name: "default scope", + config: &EntraidConfig{ + AzureRedisScopes: "", + }, + expectedScopes: []string{"https://redis.azure.com/.default"}, + }, + { + name: "custom scopes", + config: &EntraidConfig{ + AzureRedisScopes: "scope1,scope2,scope3", + }, + expectedScopes: []string{"scope1", "scope2", "scope3"}, + }, + { + name: "single scope", + config: &EntraidConfig{ + AzureRedisScopes: "single-scope", + }, + expectedScopes: []string{"single-scope"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + scopes := tt.config.GetRedisScopes() + if len(scopes) != len(tt.expectedScopes) { + t.Errorf("Expected %d scopes, got %d", len(tt.expectedScopes), len(scopes)) + return + } + for i, scope := range scopes { + if scope != tt.expectedScopes[i] { + t.Errorf("Expected scope %s at index %d, got %s", tt.expectedScopes[i], i, scope) + } + } + }) + } +} + +func TestLoadConfigDefaultPath(t *testing.T) { + // Test loading config from default path + config, err := LoadConfig("") + if err != nil { + t.Logf("Expected error when loading from default path: %v", err) + } else { + t.Log("Successfully loaded config from default path") + } + _ = config // Use config to avoid unused variable warning +} diff --git a/examples/entraid/runscript_test/main.go b/examples/entraid/runscript_test/main.go index c06f485..e1accfe 100644 --- a/examples/entraid/runscript_test/main.go +++ b/examples/entraid/runscript_test/main.go @@ -2,6 +2,10 @@ package main import "fmt" +func RunScript() string { + return "OK" +} + func main() { - fmt.Println("OK") + fmt.Println(RunScript()) } diff --git a/examples/entraid/runscript_test/main_test.go b/examples/entraid/runscript_test/main_test.go new file mode 100644 index 0000000..39ecceb --- /dev/null +++ b/examples/entraid/runscript_test/main_test.go @@ -0,0 +1,11 @@ +package main + +import "testing" + +func TestRunScript(t *testing.T) { + got := RunScript() + want := "OK" + if got != want { + t.Errorf("RunScript() = %q, want %q", got, want) + } +} From 3239bc8b31f537978f76b2082e0644baafa005f8 Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Tue, 27 May 2025 12:04:08 +0300 Subject: [PATCH 17/17] test(examples): refactor parsePrivateKey to return err --- examples/entraid/clientcert/main.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/entraid/clientcert/main.go b/examples/entraid/clientcert/main.go index dff6c30..9f947fd 100644 --- a/examples/entraid/clientcert/main.go +++ b/examples/entraid/clientcert/main.go @@ -28,6 +28,11 @@ func main() { log.Printf("Failed to load config: %v", err) } + pk, err := parsePrivateKey(cfg.AzurePrivateKey) + if err != nil { + log.Fatalf("Failed to parse private key: %v", err) + } + // Create a confidential identity credentials provider with certificate authentication cp, err := entraid.NewConfidentialCredentialsProvider(entraid.ConfidentialCredentialsProviderOptions{ CredentialsProviderOptions: entraid.CredentialsProviderOptions{ @@ -46,7 +51,7 @@ func main() { }, Scopes: cfg.GetRedisScopes(), ClientCert: parseCertificates(cfg.AzureCert), - ClientPrivateKey: parsePrivateKey(cfg.AzurePrivateKey), + ClientPrivateKey: pk, }, }) if err != nil { @@ -149,23 +154,22 @@ func decodeBase64Pem(pemData string) string { return string(decoded) } -func parsePrivateKey(base64data string) *rsa.PrivateKey { +func parsePrivateKey(base64data string) (*rsa.PrivateKey, error) { var privateKey *rsa.PrivateKey - var err error decoded := decodeBase64Pem(base64data) pk, err := x509.ParsePKCS8PrivateKey([]byte(decoded)) if err != nil { - log.Printf("Failed to parse pkcs8 key: %v", err) + return nil, fmt.Errorf("failed to parse pkcs8 key: %w", err) } privateKey, _ = pk.(*rsa.PrivateKey) if privateKey == nil { pk, err = x509.ParsePKCS1PrivateKey([]byte(decoded)) if err != nil { - log.Printf("Failed to parse pkcs1 key: %v", err) + return nil, fmt.Errorf("failed to parse pkcs1 key: %w", err) } privateKey, _ = pk.(*rsa.PrivateKey) } - return privateKey + return privateKey, nil } func parseCertificates(pemData string) []*x509.Certificate {