|
| 1 | +--- |
| 2 | +categories: |
| 3 | +- docs |
| 4 | +- develop |
| 5 | +- stack |
| 6 | +- oss |
| 7 | +- rs |
| 8 | +- rc |
| 9 | +- oss |
| 10 | +- kubernetes |
| 11 | +- clients |
| 12 | +description: Learn how to authenticate to an Azure Managed Redis (AMR) database |
| 13 | +linkTitle: Connect to AMR |
| 14 | +title: Connect to Azure Managed Redis |
| 15 | +weight: 15 |
| 16 | +--- |
| 17 | + |
| 18 | +The [`go-redis-entraid`](https://github.com/redis/go-redis-entraid) package |
| 19 | +lets you authenticate your app to |
| 20 | +[Azure Managed Redis (AMR)](https://azure.microsoft.com/en-us/products/managed-redis) |
| 21 | +using [Microsoft Entra ID](https://learn.microsoft.com/en-us/entra/identity/). |
| 22 | +You can authenticate using a system-assigned or user-assigned |
| 23 | +[managed identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) |
| 24 | +or a [service principal](https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals), |
| 25 | +letting `go-redis-entraid` fetch and renew the authentication tokens for you automatically. |
| 26 | + |
| 27 | +## Install |
| 28 | + |
| 29 | +From a Go module folder, install `go-redis-entraid` with the |
| 30 | +following command: |
| 31 | + |
| 32 | +```bash |
| 33 | +go get github.com/redis-developer/go-redis-entraid |
| 34 | +``` |
| 35 | + |
| 36 | +## Create a `StreamingCredentialsProvider` instance |
| 37 | + |
| 38 | +The `StreamingCredentialsProvider` interface defines methods |
| 39 | +to provide credentials for authentication. Use an object that |
| 40 | +implements this interface to obtain the authentication credentials you |
| 41 | +need when you connect to Redis. See the sections below to learn how |
| 42 | +to create the `StreamingCredentialsProvider` instances for AMR |
| 43 | +using the factory functions that `go-redis-entraid` provides. |
| 44 | + |
| 45 | + |
| 46 | +### `CredentialProvider` for a service principal |
| 47 | + |
| 48 | +Use the `create_from_service_principal()` factory function to create a |
| 49 | +`CredentialProvider` that authenticates to AMR using a |
| 50 | +service principal (see the |
| 51 | +[Microsoft documentation](https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals) to learn more about service principals). |
| 52 | + |
| 53 | +You will need the following details of your service principal to make the connection: |
| 54 | + |
| 55 | +- Client ID |
| 56 | +- Client secret |
| 57 | +- Tenant ID |
| 58 | + |
| 59 | +The example below shows how to import the required modules and call |
| 60 | +`create_from_service_principal()`: |
| 61 | + |
| 62 | +```python |
| 63 | +from redis import Redis |
| 64 | +from redis_entraid.cred_provider import * |
| 65 | + |
| 66 | +credential_provider = create_from_service_principal( |
| 67 | + <CLIENT_ID>, |
| 68 | + <CLIENT_SECRET>, |
| 69 | + <TENANT_ID> |
| 70 | +) |
| 71 | +``` |
| 72 | + |
| 73 | +### `StreamingCredentialsProvider` for a managed identity |
| 74 | + |
| 75 | +Use the `NewManagedIdentityCredentialsProvider()` function to create a |
| 76 | +`StreamingCredentialsProvider` that authenticates to AMR using a |
| 77 | +managed identity (see the |
| 78 | +[Microsoft documentation](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) to learn more about managed identities). |
| 79 | + |
| 80 | +The example below shows how to import the required modules and call |
| 81 | +`NewManagedIdentityCredentialsProvider()`. |
| 82 | +Pass `identity.SystemAssignedIdentity` or `identity.UserAssignedIdentity` |
| 83 | +as the `ManagedIdentityType` parameter. |
| 84 | + |
| 85 | +```go |
| 86 | +import ( |
| 87 | + "github.com/redis-developer/go-redis-entraid/entraid" |
| 88 | + "github.com/redis-developer/go-redis-entraid/identity" |
| 89 | + ... |
| 90 | +) |
| 91 | + . |
| 92 | + . |
| 93 | +provider, err := entraid.NewManagedIdentityCredentialsProvider( |
| 94 | + entraid.ManagedIdentityCredentialsProviderOptions{ |
| 95 | + CredentialsProviderOptions: entraid.CredentialsProviderOptions{ |
| 96 | + ClientID: "<your-azure-client-id>", |
| 97 | + }, |
| 98 | + ManagedIdentityType: identity.UserAssignedIdentity, |
| 99 | + UserAssignedClientID: "<your-user-assigned-client-id>", |
| 100 | + }, |
| 101 | +) |
| 102 | +``` |
| 103 | + |
| 104 | +### Custom configuration |
| 105 | + |
| 106 | +The examples above use a default configuration but you can also provide a custom |
| 107 | +configuration using the `TokenManagerOptions` field of `CredentialsProviderOptions`: |
| 108 | + |
| 109 | +```go |
| 110 | +options := entraid.CredentialsProviderOptions{ |
| 111 | + ClientID: os.Getenv("AZURE_CLIENT_ID"), |
| 112 | + TokenManagerOptions: manager.TokenManagerOptions{ |
| 113 | + ExpirationRefreshRatio: 0.7, |
| 114 | + LowerRefreshBounds: 10000, |
| 115 | + RetryOptions: manager.RetryOptions{ |
| 116 | + MaxAttempts: 3, |
| 117 | + InitialDelay: 1000 * time.Millisecond, |
| 118 | + MaxDelay: 30000 * time.Millisecond, |
| 119 | + BackoffMultiplier: 2.0, |
| 120 | + IsRetryable: func(err error) bool { |
| 121 | + return strings.Contains(err.Error(), "network error") || |
| 122 | + strings.Contains(err.Error(), "timeout") |
| 123 | + }, |
| 124 | + }, |
| 125 | + }, |
| 126 | +} |
| 127 | +``` |
| 128 | + |
| 129 | +These options are explained below: |
| 130 | + |
| 131 | +- `ExpirationRefreshRatio`: A `float` value representing the fraction |
| 132 | + of a token's lifetime that should elapse before attempting to |
| 133 | + refresh it. For example, a value of 0.75 means that you want to |
| 134 | + refresh the token after 75% of its lifetime has passed. |
| 135 | +- `LowerRefreshBounds`: The minimum amount of the token's lifetime |
| 136 | + (in milliseconds) remaining before attempting to refresh, regardless |
| 137 | + of the `expirationRefreshRatio` value. Set this to zero if you want |
| 138 | + the refresh time to depend only on `expirationRefreshRatio`. |
| 139 | +- `RetryOptions`: This object specifies how to retry a token request |
| 140 | + after failure. The available options are: |
| 141 | + - `MaxAttempts`: The maximum number of times to retry a token request |
| 142 | + The default value is 3. |
| 143 | + - `InitialDelay`: The initial delay between retries in milliseconds. This |
| 144 | + will be modified during successive attempts by the `BackoffMultiplier` |
| 145 | + value (see below). The default is 1000ms. |
| 146 | + - `BackoffMultiplier`: The factor by which the `InitialDelay` is multiplied |
| 147 | + between attempts, following an |
| 148 | + [exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) |
| 149 | + strategy. The default multiplier is 2.0. |
| 150 | + - `IsRetryable`: A function that receives an `error` parameter and returns |
| 151 | + a boolean `true` result if an attempt that failed with that error is |
| 152 | + retryable and `false` otherwise. Use this to implement your own custom |
| 153 | + logic to decide which errors should be retried. |
| 154 | + |
| 155 | + |
| 156 | +## Connect |
| 157 | + |
| 158 | +When you have created your `StreamingCredentialsProvider` instance, you are ready to |
| 159 | +connect to AMR. |
| 160 | +The example below shows how to pass the instance as a parameter to the standard |
| 161 | +`NewClient()` connection method. It also illustrates how to use |
| 162 | +[`os.Getenv()`](https://pkg.go.dev/os#Getenv) to get the connection details |
| 163 | +from environment variables rather than include their values in the code. |
| 164 | + |
| 165 | +```go |
| 166 | +package main |
| 167 | + |
| 168 | +import ( |
| 169 | + "context" |
| 170 | + "fmt" |
| 171 | + "log" |
| 172 | + "os" |
| 173 | + "strings" |
| 174 | + |
| 175 | + "github.com/redis-developer/go-redis-entraid/entraid" |
| 176 | + "github.com/redis/go-redis/v9" |
| 177 | +) |
| 178 | + |
| 179 | +func main() { |
| 180 | + // Get required environment variables |
| 181 | + clientID := os.Getenv("AZURE_CLIENT_ID") |
| 182 | + redisEndpoint := os.Getenv("REDIS_ENDPOINT") |
| 183 | + if clientID == "" || redisEndpoint == "" { |
| 184 | + log.Fatal( |
| 185 | + "AZURE_CLIENT_ID and REDIS_ENDPOINT env variables are required" |
| 186 | + ) |
| 187 | + } |
| 188 | + |
| 189 | + // Create credentials provider |
| 190 | + provider, err := entraid.NewManagedIdentityCredentialsProvider( |
| 191 | + entraid.ManagedIdentityCredentialsProviderOptions{ |
| 192 | + CredentialsProviderOptions: entraid.CredentialsProviderOptions{ |
| 193 | + ClientID: clientID, |
| 194 | + }, |
| 195 | + } |
| 196 | + ) |
| 197 | + if err != nil { |
| 198 | + log.Fatalf("Failed to create credentials provider: %v", err) |
| 199 | + } |
| 200 | + |
| 201 | + // Create Redis client |
| 202 | + client := redis.NewClient(&redis.Options{ |
| 203 | + Addr: redisEndpoint, |
| 204 | + StreamingCredentialsProvider: provider, |
| 205 | + }) |
| 206 | + defer client.Close() |
| 207 | + |
| 208 | + // Test connection |
| 209 | + ctx := context.Background() |
| 210 | + if err := client.Ping(ctx).Err(); err != nil { |
| 211 | + log.Fatalf("Failed to connect to Redis: %v", err) |
| 212 | + } |
| 213 | + log.Println("Connected to Redis!") |
| 214 | +} |
| 215 | +``` |
0 commit comments