Skip to content

Commit 2718c8f

Browse files
committed
Add Akeyless Secrets Store Component
Signed-off-by: Kobbi Gal <kobbi.g@akeyless.io>
1 parent 5937bd6 commit 2718c8f

File tree

7 files changed

+3021
-8
lines changed

7 files changed

+3021
-8
lines changed

go.mod

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module github.com/dapr/components-contrib
22

3-
go 1.24.4
3+
go 1.24.6
4+
5+
toolchain go1.24.10
46

57
require (
68
cloud.google.com/go/datastore v1.20.0
@@ -58,13 +60,14 @@ require (
5860
github.com/cenkalti/backoff/v4 v4.3.0
5961
github.com/chebyrash/promise v0.0.0-20230709133807-42ec49ba1459
6062
github.com/cinience/go_rocketmq v0.0.2
61-
github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.14.0
63+
github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.2
6264
github.com/cloudevents/sdk-go/v2 v2.15.2
6365
github.com/cloudwego/kitex v0.5.0
6466
github.com/cloudwego/kitex-examples v0.1.1
6567
github.com/cyphar/filepath-securejoin v0.2.4
6668
github.com/dancannon/gorethink v4.0.0+incompatible
67-
github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5
69+
github.com/dapr/components-contrib/tests/certification v0.0.0-20251104160704-920ad8a7b958
70+
github.com/dapr/kit v0.16.1
6871
github.com/didip/tollbooth/v7 v7.0.1
6972
github.com/eclipse/paho.mqtt.golang v1.4.3
7073
github.com/fasthttp-contrib/sessions v0.0.0-20160905201309-74f6ac73d5d5
@@ -418,7 +421,6 @@ require (
418421
go.opentelemetry.io/otel/sdk v1.35.0 // indirect
419422
go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect
420423
go.opentelemetry.io/otel/trace v1.35.0 // indirect
421-
go.opentelemetry.io/proto/otlp v1.6.0 // indirect
422424
go.uber.org/atomic v1.10.0 // indirect
423425
go.uber.org/zap v1.27.0 // indirect
424426
golang.org/x/arch v0.10.0 // indirect

go.sum

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,8 @@ github.com/clbanning/mxj/v2 v2.5.6 h1:Jm4VaCI/+Ug5Q57IzEoZbwx4iQFA6wkXv72juUSeK+
421421
github.com/clbanning/mxj/v2 v2.5.6/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
422422
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
423423
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
424-
github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.14.0 h1:dEopBSOSjB5fM9r76ufM44AVj9Dnz2IOM0Xs6FVxZRM=
425-
github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.14.0/go.mod h1:qDSbb0fgIfFNjZrNTPtS5MOMScAGyQtn1KlSvoOdqYw=
424+
github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.2 h1:FIvfKlS2mcuP0qYY6yzdIU9xdrRd/YMP0bNwFjXd0u8=
425+
github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.2/go.mod h1:POsdVp/08Mki0WD9QvvgRRpg9CQ6zhjfRrBoEY8JFS8=
426426
github.com/cloudevents/sdk-go/v2 v2.15.2 h1:54+I5xQEnI73RBhWHxbI1XJcqOFOVJN85vb41+8mHUc=
427427
github.com/cloudevents/sdk-go/v2 v2.15.2/go.mod h1:lL7kSWAE/V8VI4Wh0jbL2v/jvqsm6tjmaQBSvxcv4uE=
428428
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg=
@@ -516,8 +516,10 @@ github.com/dancannon/gorethink v4.0.0+incompatible h1:KFV7Gha3AuqT+gr0B/eKvGhbjm
516516
github.com/dancannon/gorethink v4.0.0+incompatible/go.mod h1:BLvkat9KmZc1efyYwhz3WnybhRZtgF1K929FD8z1avU=
517517
github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
518518
github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
519-
github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5 h1:Q26gmPxs6WnnBYoudOlznPHsmrbTawcYEpHg4VoB7v8=
520-
github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5/go.mod h1:40ZWs5P6xfYf7O59XgwqZkIyDldTIXlhTQhGop8QoSM=
519+
github.com/dapr/components-contrib/tests/certification v0.0.0-20251104160704-920ad8a7b958 h1:DSZgzdXlbF75fwvEkMQpPqn1jjxmWVoBNmI4Bc4dS40=
520+
github.com/dapr/components-contrib/tests/certification v0.0.0-20251104160704-920ad8a7b958/go.mod h1:IUB5RJv0Gj5qxsHjjhvEBIlxPka7cD7KAn/Coa2y27M=
521+
github.com/dapr/kit v0.16.1 h1:MqLAhHVg8trPy2WJChMZFU7ToeondvxcNHYVvMDiVf4=
522+
github.com/dapr/kit v0.16.1/go.mod h1:40ZWs5P6xfYf7O59XgwqZkIyDldTIXlhTQhGop8QoSM=
521523
github.com/dave/jennifer v1.4.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
522524
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
523525
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=

secretstores/akeyless/README.md

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# Akeyless Secret Store
2+
3+
This component provides a Dapr secret store implementation for [Akeyless](https://www.akeyless.io/), a cloud-native secrets management platform.
4+
5+
## Configuration
6+
7+
The Akeyless Dapr Secret Store component only supports the following [Authentication Methods](https://docs.akeyless.io/docs/access-and-authentication-methods):
8+
9+
- [API Key](https://docs.akeyless.io/docs/api-key)
10+
- [OAuth2.0/JWT](https://docs.akeyless.io/docs/oauth20jwt)
11+
- [AWS IAM](https://docs.akeyless.io/docs/aws-iam)
12+
- [Kubernetes](https://docs.akeyless.io/docs/kubernetes-auth)
13+
14+
### Authentication
15+
16+
The Akeyless secret store component supports the following configuration options:
17+
18+
| Field | Required | Description | Example |
19+
|-------|----------|-------------|---------|
20+
| `gatewayUrl` | No | The Akeyless Gateway URL. Default is https://api.akeyless.io. | `https://your-gateway.akeyless.io` |
21+
| `accessId` | Yes | The Akeyless authentication access ID. | `p-123456780wm` |
22+
| `jwt` | No | If using an OAuth2.0/JWT access ID, specify the JSON Web Token | `eyJ...` |
23+
| `accessKey` | No | If using an API Key access ID, specify the API key | `ABCD123...=` |
24+
| `k8sAuthConfigName` | No | If using the k8s auth method, specify the name of the k8s auth config. | `k8s-auth-config` |
25+
| `k8sGatewayUrl` | No | The gateway URL that where the k8s auth config is located. | `http://gw.akeyless.svc.cluster.local:8000` |
26+
| `k8sServiceAccountToken` | No | If using the k8s auth method, specify the service account token. If not specified,
27+
we will try to read it from the default service account token file. | `eyJ...` |
28+
29+
30+
31+
## Examples
32+
33+
We currently support the following [Authentication Methods](https://docs.akeyless.io/docs/access-and-authentication-methods):
34+
35+
36+
## Examples
37+
38+
## Example Configuration: API Key
39+
40+
```yaml
41+
apiVersion: dapr.io/v1alpha1
42+
kind: Component
43+
metadata:
44+
name: akeyless-secretstore
45+
spec:
46+
type: secretstores.akeyless
47+
version: v1
48+
metadata:
49+
- name: gatewayUrl
50+
value: "https://your-gateway.akeyless.io"
51+
- name: accessId
52+
value: "p-1234Abcdam"
53+
- name: accessKey
54+
value: "ABCD1233...="
55+
```
56+
57+
58+
## Example Configuration: JWT
59+
60+
```yaml
61+
apiVersion: dapr.io/v1alpha1
62+
kind: Component
63+
metadata:
64+
name: akeyless-secretstore
65+
spec:
66+
type: secretstores.akeyless
67+
version: v1
68+
metadata:
69+
- name: gatewayUrl
70+
value: "https://your-gateway.akeyless.io"
71+
- name: accessId
72+
value: "p-1234Abcdom"
73+
- name: jwt
74+
value: "eyJ....."
75+
```
76+
77+
## Example Configuration: AWS IAM
78+
79+
```yaml
80+
apiVersion: dapr.io/v1alpha1
81+
kind: Component
82+
metadata:
83+
name: akeyless
84+
spec:
85+
type: secretstores.akeyless
86+
version: v1
87+
metadata:
88+
- name: gatewayUrl
89+
value: "https://your-gateway.akeyless.io"
90+
- name: accessId
91+
value: "p-1234Abcdwm"
92+
```
93+
94+
## Example Configuration: Kubernetes
95+
96+
```yaml
97+
apiVersion: dapr.io/v1alpha1
98+
kind: Component
99+
metadata:
100+
name: akeyless
101+
spec:
102+
type: secretstores.akeyless
103+
version: v1
104+
metadata:
105+
- name: gatewayUrl
106+
value: "https://gw.akeyless.svc.cluster.local"
107+
- name: accessId
108+
value: "p-1234Abcdwm"
109+
- name: k8sAuthConfigName
110+
value: "us-east-1-prod-akeyless-k8s-conf"
111+
- name: k8sGatewayUrl
112+
value: https://gw.akeyless.svc.cluster.local
113+
```
114+
115+
## Usage
116+
117+
Once configured, you can retrieve secrets using the Dapr secrets API:
118+
119+
```bash
120+
# Get a single secret
121+
curl http://localhost:3500/v1.0/secrets/akeyless/my-secret
122+
123+
# Get all secrets (static, dynamic, rotated) from root (/) path
124+
curl http://localhost:3500/v1.0/secrets/akeyless/bulk
125+
126+
# Get all secrets static secrets
127+
curl http://localhost:3500/v1.0/secrets/akeyless/bulk?metadata.secrets_type=static
128+
129+
# Get all static and dynamic secrets from a specific path (/my/org)
130+
curl http://localhost:3500/v1.0/secrets/akeyless/bulk?metadata.secrets_type=static,dynamic&metadata.path=/my/org
131+
```
132+
133+
Or using the Dapr SDK. The example below retrieves all static secrets from path `/path/to/department`.
134+
```go
135+
log.Println("Starting test application")
136+
client, err := dapr.NewClient()
137+
if err != nil {
138+
log.Printf("Error creating Dapr client: %v\n", err)
139+
panic(err)
140+
}
141+
log.Println("Dapr client created successfully")
142+
const daprSecretStore = "akeyless"
143+
144+
defer client.Close()
145+
ctx := context.Background()
146+
akeylessBulkMetadata := map[string]string{
147+
"path": "/path/to/department",
148+
"secrets_type": "static",
149+
}
150+
secrets, err := client.GetBulkSecret(ctx, daprSecretStore, akeylessBulkMetadata)
151+
if err != nil {
152+
log.Printf("Error fetching secrets: %v\n", err)
153+
panic(err)
154+
}
155+
log.Printf("Found %d secrets: ", len(secrets))
156+
for secretName, secretValue := range secrets {
157+
log.Printf("Secret: %s, Value: %s", secretName, secretValue)
158+
}
159+
```
160+
161+
## Features
162+
163+
- Supports static, dynamic and rotated secrets.
164+
- **GetSecret**: Retrieve an individual value secret by path.
165+
- **BulkGetSecret**: Retrieve all secrets from a specified path (or `/` by default) recursively.
166+
167+
## Response Formats
168+
169+
The Akeyless secret store returns different response formats depending on the secret type:
170+
171+
### Static Secrets
172+
Static secrets return their value directly as a string:
173+
174+
```json
175+
{
176+
"my-static-secret": "secret-value"
177+
}
178+
```
179+
180+
### Dynamic Secrets
181+
Dynamic secrets return a JSON string containing the credentials. The exact structure depends on the target system:
182+
183+
**MySQL Dynamic Secret:**
184+
```json
185+
{
186+
"my-mysql-secret": "{\"user\":\"generated_username\",\"password\":\"generated_password\",\"ttl_in_minutes\":\"60\",\"id\":\"username\"}"
187+
}
188+
```
189+
190+
**Azure AD Dynamic Secret:**
191+
```json
192+
{
193+
"my-azure-secret": "{\"user\":{\"id\":\"user_id\",\"displayName\":\"user_name\",\"mail\":\"email@domain.com\"},\"secret\":{\"keyId\":\"secret_key_id\",\"displayName\":\"secret_name\",\"tenantId\":\"tenant_id\"},\"ttl_in_minutes\":\"60\",\"id\":\"user_id\",\"msg\":\"User has been added successfully...\"}"
194+
}
195+
```
196+
197+
**GCP Dynamic Secret:**
198+
```json
199+
{
200+
"my-gcp-secret": "{\"encoded_key\":\"base64_encoded_service_account_key\",\"ttl_in_minutes\":\"60\",\"id\":\"service_account_name\"}"
201+
}
202+
```
203+
204+
### Rotated Secrets
205+
Rotated secrets return a JSON object containing all available fields:
206+
207+
```json
208+
{
209+
"my-rotated-secret": "{\"value\":{\"username\":\"rotated_user\",\"password\":\"rotated_password\",\"application_id\":\"1234567890\"}}"
210+
}
211+
```
212+
213+
**Note:** The exact fields in dynamic and rotated secret responses vary by target system and configuration. Applications should parse the JSON string to extract the specific credentials they need.

0 commit comments

Comments
 (0)