|
| 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 | +Install [`go-redis`]({{< relref "/develop/clients/go" >}}) if you |
| 30 | +have not already done so. Note that `go-redis-entraid` |
| 31 | +requires `go-redis` v9.9.0 or above, so you should upgrade if you |
| 32 | +are using an earlier version. |
| 33 | + |
| 34 | +Install `go-redis-entraid` with the following command: |
| 35 | + |
| 36 | +```bash |
| 37 | +go get github.com/redis/go-redis-entraid |
| 38 | +``` |
| 39 | + |
| 40 | +## Create a `StreamingCredentialsProvider` instance |
| 41 | + |
| 42 | +The `StreamingCredentialsProvider` interface defines methods |
| 43 | +to provide credentials for authentication. Use an object that |
| 44 | +implements this interface to obtain the authentication credentials you |
| 45 | +need when you connect to Redis. See the sections below to learn how |
| 46 | +to create the `StreamingCredentialsProvider` instances for AMR |
| 47 | +using the factory functions that `go-redis-entraid` provides. |
| 48 | + |
| 49 | + |
| 50 | +### `StreamingCredentialsProvider` for a service principal |
| 51 | + |
| 52 | +Use the `NewConfidentialCredentialsProvider()` factory function to create a |
| 53 | +`StreamingCredentialsProvider` that authenticates to AMR using a |
| 54 | +service principal (see the |
| 55 | +[Microsoft documentation](https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals) to learn more about service principals). |
| 56 | + |
| 57 | +You will need the following details of your service principal to make the connection: |
| 58 | + |
| 59 | +- Client ID |
| 60 | +- Client secret |
| 61 | +- Tenant ID |
| 62 | + |
| 63 | +Use an `AuthorityConfiguration` instance to pass the tenant ID. |
| 64 | +This type has the following fields: |
| 65 | + |
| 66 | +- `AuthorityType`: This should have one of the values |
| 67 | + - `identity.AuthorityTypeDefault` ("default") |
| 68 | + - `identity.AuthorityTypeMultiTenant` ("multi-tenant") |
| 69 | + - `identity.AuthorityTypeCustom` ("custom") |
| 70 | +- `TenantID`: Pass your tenant ID string here, or use "common" for |
| 71 | + a multi-tentant application. |
| 72 | +- `Authority`: Custom authority URL. This is only required if you |
| 73 | + specified `AuthorityTypeCustom` in the `AuthorityType` field. |
| 74 | + |
| 75 | +The example below shows how to import the required modules and call |
| 76 | +`NewConfidentialCredentialsProvider()`: |
| 77 | + |
| 78 | +```go |
| 79 | +import ( |
| 80 | + "github.com/redis-developer/go-redis-entraid/entraid" |
| 81 | + "github.com/redis-developer/go-redis-entraid/identity" |
| 82 | + ... |
| 83 | +) |
| 84 | + . |
| 85 | + . |
| 86 | +provider, err := entraid.NewConfidentialCredentialsProvider( |
| 87 | + entraid.ConfidentialCredentialsProviderOptions{ |
| 88 | + ConfidentialIdentityProviderOptions: identity.ConfidentialIdentityProviderOptions{ |
| 89 | + ClientID: "<your-azure-client-id>", |
| 90 | + ClientSecret: "<your-azure-client-secret>", |
| 91 | + CredentialsType: identity.ClientSecretCredentialType, |
| 92 | + Authority: identity.AuthorityConfiguration{ |
| 93 | + AuthorityType: identity.AuthorityTypeDefault, |
| 94 | + TenantID: "<your-azure-tenant-id>", |
| 95 | + }, |
| 96 | + }, |
| 97 | + }, |
| 98 | +) |
| 99 | +``` |
| 100 | + |
| 101 | +### `StreamingCredentialsProvider` for a managed identity |
| 102 | + |
| 103 | +Use the `NewManagedIdentityCredentialsProvider()` function to create a |
| 104 | +`StreamingCredentialsProvider` that authenticates to AMR using a |
| 105 | +managed identity (see the |
| 106 | +[Microsoft documentation](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) to learn more about managed identities). |
| 107 | + |
| 108 | +The example below shows how to import the required modules and call |
| 109 | +`NewManagedIdentityCredentialsProvider()`. |
| 110 | +Pass `identity.SystemAssignedIdentity` or `identity.UserAssignedIdentity` |
| 111 | +as the `ManagedIdentityType` parameter. |
| 112 | + |
| 113 | +```go |
| 114 | +import ( |
| 115 | + "github.com/redis-developer/go-redis-entraid/entraid" |
| 116 | + "github.com/redis-developer/go-redis-entraid/identity" |
| 117 | + ... |
| 118 | +) |
| 119 | + . |
| 120 | + . |
| 121 | +provider, err := entraid.NewManagedIdentityCredentialsProvider( |
| 122 | + entraid.ManagedIdentityCredentialsProviderOptions{ |
| 123 | + ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ |
| 124 | + ManagedIdentityType: identity.UserAssignedObjectID, |
| 125 | + UserAssignedObjectID: "<your-user-assigned-client-id>", |
| 126 | + }, |
| 127 | + }, |
| 128 | +) |
| 129 | +``` |
| 130 | + |
| 131 | +### Custom configuration |
| 132 | + |
| 133 | +The examples above use a default configuration but you can also provide a custom |
| 134 | +configuration using the `TokenManagerOptions` field of `CredentialsProviderOptions`: |
| 135 | + |
| 136 | +```go |
| 137 | +options := entraid.CredentialsProviderOptions{ |
| 138 | + TokenManagerOptions: manager.TokenManagerOptions{ |
| 139 | + ExpirationRefreshRatio: 0.7, |
| 140 | + LowerRefreshBounds: 10000, |
| 141 | + RetryOptions: manager.RetryOptions{ |
| 142 | + MaxAttempts: 3, |
| 143 | + InitialDelay: 1000 * time.Millisecond, |
| 144 | + MaxDelay: 30000 * time.Millisecond, |
| 145 | + BackoffMultiplier: 2.0, |
| 146 | + IsRetryable: func(err error) bool { |
| 147 | + return strings.Contains(err.Error(), "network error") || |
| 148 | + strings.Contains(err.Error(), "timeout") |
| 149 | + }, |
| 150 | + }, |
| 151 | + }, |
| 152 | +} |
| 153 | +``` |
| 154 | + |
| 155 | +You can then pass this configuration when you create the |
| 156 | +`StreamingCredentialsProvider`. The example below shows how to do this |
| 157 | +with the `NewManagedIdentityCredentialsProvider()` method: |
| 158 | + |
| 159 | +```go |
| 160 | +provider, err := entraid.NewManagedIdentityCredentialsProvider( |
| 161 | + entraid.ManagedIdentityCredentialsProviderOptions{ |
| 162 | + CredentialsProviderOptions: options, |
| 163 | + ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ |
| 164 | + ManagedIdentityType: identity.UserAssignedObjectID, |
| 165 | + UserAssignedObjectID: "<your-user-assigned-client-id>", |
| 166 | + }, |
| 167 | + }, |
| 168 | +) |
| 169 | +``` |
| 170 | + |
| 171 | +The fields of `TokenManagerOptions` are explained below: |
| 172 | + |
| 173 | +- `ExpirationRefreshRatio`: A `float` value representing the fraction |
| 174 | + of a token's lifetime that should elapse before attempting to |
| 175 | + refresh it. For example, a value of 0.75 means that you want to |
| 176 | + refresh the token after 75% of its lifetime has passed. |
| 177 | +- `LowerRefreshBounds`: The minimum amount of the token's lifetime |
| 178 | + (in milliseconds) remaining before attempting to refresh, regardless |
| 179 | + of the `expirationRefreshRatio` value. Set this to zero if you want |
| 180 | + the refresh time to depend only on `expirationRefreshRatio`. |
| 181 | +- `RetryOptions`: This object specifies how to retry a token request |
| 182 | + after failure. The available options are: |
| 183 | + - `MaxAttempts`: The maximum number of times to retry a token request |
| 184 | + The default value is 3. |
| 185 | + - `InitialDelay`: The initial delay between retries in milliseconds. This |
| 186 | + will be modified during successive attempts by the `BackoffMultiplier` |
| 187 | + value (see below). The default is 1000ms. |
| 188 | + - `BackoffMultiplier`: The factor by which the `InitialDelay` is multiplied |
| 189 | + between attempts, following an |
| 190 | + [exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) |
| 191 | + strategy. The default multiplier is 2.0. |
| 192 | + - `IsRetryable`: A function that receives an `error` parameter and returns |
| 193 | + a boolean `true` result if an attempt that failed with that error is |
| 194 | + retryable and `false` otherwise. Use this to implement your own custom |
| 195 | + logic to decide which errors should be retried. |
| 196 | + |
| 197 | + |
| 198 | +## Connect |
| 199 | + |
| 200 | +When you have created your `StreamingCredentialsProvider` instance, you are ready to |
| 201 | +connect to AMR. |
| 202 | +The example below shows how to pass the instance as a parameter to the standard |
| 203 | +`NewClient()` connection method. It also illustrates how to use |
| 204 | +[`os.Getenv()`](https://pkg.go.dev/os#Getenv) to get the connection details |
| 205 | +from environment variables rather than include their values in the code. |
| 206 | + |
| 207 | +```go |
| 208 | +package main |
| 209 | + |
| 210 | +import ( |
| 211 | + "context" |
| 212 | + "fmt" |
| 213 | + "log" |
| 214 | + "os" |
| 215 | + "strings" |
| 216 | + |
| 217 | + "github.com/redis-developer/go-redis-entraid/entraid" |
| 218 | + "github.com/redis/go-redis/v9" |
| 219 | +) |
| 220 | + |
| 221 | +func main() { |
| 222 | + // Get required environment variables |
| 223 | + redisEndpoint := os.Getenv("REDIS_ENDPOINT") |
| 224 | + if redisEndpoint == "" { |
| 225 | + log.Fatal( |
| 226 | + "REDIS_ENDPOINT environment variable is required" |
| 227 | + ) |
| 228 | + } |
| 229 | + |
| 230 | + // Create credentials provider for system assigned identity |
| 231 | + provider, err := entraid.NewManagedIdentityCredentialsProvider( |
| 232 | + entraid.ManagedIdentityCredentialsProviderOptions{ |
| 233 | + ManagedIdentityProviderOptions: identity.ManagedIdentityProviderOptions{ |
| 234 | + ManagedIdentityType: identity.SystemAssignedIdentity, |
| 235 | + }, |
| 236 | + } |
| 237 | + ) |
| 238 | + if err != nil { |
| 239 | + log.Fatalf("Failed to create credentials provider: %v", err) |
| 240 | + } |
| 241 | + |
| 242 | + // Create Redis client |
| 243 | + client := redis.NewClient(&redis.Options{ |
| 244 | + Addr: redisEndpoint, |
| 245 | + StreamingCredentialsProvider: provider, |
| 246 | + }) |
| 247 | + defer client.Close() |
| 248 | + |
| 249 | + // Test connection |
| 250 | + ctx := context.Background() |
| 251 | + if err := client.Ping(ctx).Err(); err != nil { |
| 252 | + log.Fatalf("Failed to connect to Redis: %v", err) |
| 253 | + } |
| 254 | + log.Println("Connected to Redis!") |
| 255 | +} |
| 256 | +``` |
| 257 | + |
| 258 | +## More information |
| 259 | + |
| 260 | +See the [`go-redis-entraid`](https://github.com/redis/go-redis-entraid) |
| 261 | +GitHub repository for full source code and more examples and details. |
0 commit comments