Skip to content

Commit

Permalink
Adding Kubernetes native secrets to secret stores (radius-project#7744)
Browse files Browse the repository at this point in the history
# Description
Adding secret store capabilities to reference kubernetes secrets
natively

## Type of change

- This pull request adds or changes features of Radius and has an
approved issue (radius-project#5520) .


<!--

Please update the following to link the associated issue. This is
required for some kinds of changes (see above).

-->

Fixes: radius-project#5520

---------

Signed-off-by: Nick Beenham <[email protected]>
  • Loading branch information
superbeeny authored Sep 3, 2024
1 parent 96d5cf8 commit 3ddb61e
Show file tree
Hide file tree
Showing 35 changed files with 1,232 additions and 310 deletions.

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions hack/bicep-types-radius/generated/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/53"
},
"Applications.Core/containers@2023-10-01-preview": {
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/119"
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/122"
},
"Applications.Core/environments@2023-10-01-preview": {
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/157"
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/159"
},
"Applications.Core/extenders@2023-10-01-preview": {
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/176"
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/178"
},
"Applications.Core/gateways@2023-10-01-preview": {
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/197"
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/199"
},
"Applications.Core/secretStores@2023-10-01-preview": {
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/232"
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/234"
},
"Applications.Core/volumes@2023-10-01-preview": {
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/269"
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/271"
},
"Applications.Dapr/pubSubBrokers@2023-10-01-preview": {
"$ref": "applications/applications.dapr/2023-10-01-preview/types.json#/44"
Expand Down
73 changes: 70 additions & 3 deletions pkg/corerp/api/v20231001preview/container_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package v20231001preview

import (
"encoding/json"
"fmt"

v1 "github.com/radius-project/radius/pkg/armrpc/api/v1"
"github.com/radius-project/radius/pkg/corerp/datamodel"
Expand Down Expand Up @@ -101,6 +102,11 @@ func (src *ContainerResource) ConvertTo() (v1.DataModelInterface, error) {
}
}

convertedEnvironmentVariables, err := toEnvironmentVariableDataModel(src.Properties.Container.Env)
if err != nil {
return nil, err
}

converted := &datamodel.ContainerResource{
BaseResource: v1.BaseResource{
TrackedResource: v1.TrackedResource{
Expand All @@ -123,7 +129,7 @@ func (src *ContainerResource) ConvertTo() (v1.DataModelInterface, error) {
Container: datamodel.Container{
Image: to.String(src.Properties.Container.Image),
ImagePullPolicy: toImagePullPolicyDataModel(src.Properties.Container.ImagePullPolicy),
Env: to.StringMap(src.Properties.Container.Env),
Env: convertedEnvironmentVariables,
LivenessProbe: livenessProbe,
Ports: ports,
ReadinessProbe: readinessProbe,
Expand All @@ -147,10 +153,71 @@ func (src *ContainerResource) ConvertTo() (v1.DataModelInterface, error) {
Resource: to.String(src.Properties.Identity.Resource),
}
}

return converted, nil
}

// toEnvironmentVariableDataModel: Converts from versioned datamodel to base datamodel
func toEnvironmentVariableDataModel(e map[string]*EnvironmentVariable) (map[string]datamodel.EnvironmentVariable, error) {
environmentVariableMap := map[string]datamodel.EnvironmentVariable{}

for key, val := range e {
if val == nil {
return nil, v1.NewClientErrInvalidRequest(fmt.Sprintf("Environment variable %s is nil", key))
}
// An environment variable can have either value(Value) or secret value(ValueFrom), but not both
if val.Value != nil && val.ValueFrom != nil {
return nil, v1.NewClientErrInvalidRequest(fmt.Sprintf("Environment variable %s has both value and secret value", key))
}

// An environment variable must have either value(Value) or secret value(ValueFrom)
if val.Value == nil && val.ValueFrom == nil {
return nil, v1.NewClientErrInvalidRequest(fmt.Sprintf("Environment variable %s has neither value nor secret value", key))
}

if val.Value != nil {
environmentVariableMap[key] = datamodel.EnvironmentVariable{
Value: val.Value,
}
} else {
environmentVariableMap[key] = datamodel.EnvironmentVariable{
ValueFrom: &datamodel.EnvironmentVariableReference{
SecretRef: &datamodel.EnvironmentVariableSecretReference{
Source: to.String(val.ValueFrom.SecretRef.Source),
Key: to.String(val.ValueFrom.SecretRef.Key),
},
},
}

}

}
return environmentVariableMap, nil
}

// fromEnvironmentVariableDataModel: Converts from base datamodel to versioned datamodel
func fromEnvironmentVariableDataModel(e map[string]datamodel.EnvironmentVariable) map[string]*EnvironmentVariable {
environmentVariableMap := map[string]*EnvironmentVariable{}

for key, val := range e {
if val.Value != nil {
environmentVariableMap[key] = &EnvironmentVariable{
Value: val.Value,
}
} else if val.ValueFrom != nil {
environmentVariableMap[key] = &EnvironmentVariable{
ValueFrom: &EnvironmentVariableReference{
SecretRef: &SecretReference{
Source: to.Ptr(val.ValueFrom.SecretRef.Source),
Key: to.Ptr(val.ValueFrom.SecretRef.Key),
},
},
}
}
}

return environmentVariableMap
}

// ConvertFrom converts from version-agnostic datamodel to the versioned Container resource.
func (dst *ContainerResource) ConvertFrom(src v1.DataModelInterface) error {
c, ok := src.(*datamodel.ContainerResource)
Expand Down Expand Up @@ -250,7 +317,7 @@ func (dst *ContainerResource) ConvertFrom(src v1.DataModelInterface) error {
Container: &Container{
Image: to.Ptr(c.Properties.Container.Image),
ImagePullPolicy: fromImagePullPolicyDataModel(c.Properties.Container.ImagePullPolicy),
Env: *to.StringMapPtr(c.Properties.Container.Env),
Env: fromEnvironmentVariableDataModel(c.Properties.Container.Env),
LivenessProbe: livenessProbe,
Ports: ports,
ReadinessProbe: readinessProbe,
Expand Down
37 changes: 37 additions & 0 deletions pkg/corerp/api/v20231001preview/container_conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ func TestContainerConvertVersionedToDataModel(t *testing.T) {
err: nil,
emptyExt: true,
},
{
filename: "containerresource-nil-env-variables.json",
err: v1.NewClientErrInvalidRequest("Environment variable DB_USER has neither value nor secret value"),
emptyExt: false,
},
}

for _, tt := range conversionTests {
Expand Down Expand Up @@ -91,6 +96,22 @@ func TestContainerConvertVersionedToDataModel(t *testing.T) {
return
}

if tt.filename == "containerresource.json" {
require.Equal(t, map[string]datamodel.EnvironmentVariable{
"DB_USER": {
Value: to.Ptr("DB_USER"),
},
"DB_PASSWORD": {
ValueFrom: &datamodel.EnvironmentVariableReference{
SecretRef: &datamodel.EnvironmentVariableSecretReference{
Source: "secret.id",
Key: "DB_PASSWORD",
},
},
},
}, ct.Properties.Container.Env)
}

val, ok := ct.Properties.Connections["inventory"]
require.True(t, ok)
require.Equal(t, "inventory_route_id", val.Source)
Expand Down Expand Up @@ -176,6 +197,22 @@ func TestContainerConvertDataModelToVersioned(t *testing.T) {
return
}

if tt.filename == "containerresourcedatamodel.json" {
require.Equal(t, map[string]datamodel.EnvironmentVariable{
"DB_USER": {
Value: to.Ptr("DB_USER"),
},
"DB_PASSWORD": {
ValueFrom: &datamodel.EnvironmentVariableReference{
SecretRef: &datamodel.EnvironmentVariableSecretReference{
Source: "secret.id",
Key: "DB_PASSWORD",
},
},
},
}, r.Properties.Container.Env)
}

val, ok := r.Properties.Connections["inventory"]
require.True(t, ok)
require.Equal(t, "inventory_route_id", val.Source)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/radius-test-rg/providers/Applications.Core/containers/container0",
"name": "container0",
"type": "Applications.Core/containers",
"properties": {
"status": {
"outputResources": [
{
"id": "/planes/test/local/providers/Test.Namespace/testResources/test-resource"
}
]
},
"provisioningState": "Succeeded",
"application": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Applications.Core/applications/app0",
"connections": {
"inventory": {
"source": "inventory_route_id",
"disableDefaultEnvVars": true,
"iam": {
"kind": "azure",
"roles": [
"read"
]
}
}
},
"restartPolicy": "Always",
"container": {
"image": "ghcr.io/radius-project/webapptutorial-todoapp",
"livenessProbe": {
"kind": "tcp",
"failureThreshold": 5,
"initialDelaySeconds": 5,
"periodSeconds": 5,
"timeoutSeconds": 5,
"containerPort": 8080
},
"env": {
"DB_USER": { }
},
"command": [
"/bin/sh"
],
"args": [
"-c",
"while true; do echo hello; sleep 10;done"
],
"workingDir": "/app"
},
"identity": {
"kind": "azure.com.workload",
"oidcIssuer": "https://oidcuri/id",
"resource": "resourceid"
},
"extensions": [
{
"kind": "manualScaling",
"replicas": 2
},
{
"kind": "daprSidecar",
"appId": "app-id",
"appPort": 80,
"config": "config",
"protocol": "http"
},
{
"kind": "kubernetesMetadata",
"annotations": {
"prometheus.io/scrape": "true",
"prometheus.io/port": "80"
},
"labels": {
"foo/bar/team": "credit",
"foo/bar/contact": "radiususer"
}
}
]
}
}
11 changes: 11 additions & 0 deletions pkg/corerp/api/v20231001preview/testdata/containerresource.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@
"timeoutSeconds": 5,
"containerPort": 8080
},
"env": {
"DB_USER": { "value": "DB_USER" },
"DB_PASSWORD": {
"valueFrom": {
"secretRef": {
"source": "secret.id",
"key": "DB_PASSWORD"
}
}
}
},
"command": [
"/bin/sh"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@
"containerPort": 8080
}
},
"env": {
"DB_USER": { "value": "DB_USER" },
"DB_PASSWORD": {
"valueFrom": {
"secretRef": {
"source": "secret.id",
"key": "DB_PASSWORD"
}
}
}
},
"command": [
"/bin/sh"
],
Expand Down
44 changes: 42 additions & 2 deletions pkg/corerp/api/v20231001preview/zz_generated_models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3ddb61e

Please sign in to comment.