Secure Redfish endpoint with BasicAuth
This sets up a reverse proxy using nginx to put basic auth in front of the sushy emulator. Change-Id: Ia34195daa41793aaebbe80af3450925f514da6a8
This commit is contained in:
parent
f79c236c02
commit
39b9b57b15
@ -50,17 +50,19 @@ spec:
|
||||
- name: etc-storage
|
||||
mountPath: /etc/libvirt/storage
|
||||
- name: sushy
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
hostPort: 8000
|
||||
image: quay.io/metal3-io/sushy-tools
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["/usr/local/bin/sushy-emulator"]
|
||||
command: ["/usr/local/bin/sushy-emulator", "--port", "5000"]
|
||||
volumeMounts:
|
||||
- name: var-run-libvirt
|
||||
mountPath: /var/run/libvirt
|
||||
- name: var-lib-libvirt
|
||||
mountPath: /var/lib/libvirt
|
||||
- name: vino-reverse-proxy
|
||||
image: quay.io/airshipit/vino-reverse-proxy
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
hostPort: 8000
|
||||
- name: labeler
|
||||
image: quay.io/airshipit/nodelabeler
|
||||
imagePullPolicy: IfNotPresent
|
||||
|
@ -39,6 +39,14 @@ const (
|
||||
VinoNodeNetworkValuesAnnotation = "airshipit.org/vino.network-values"
|
||||
)
|
||||
|
||||
// Constants for BasicAuth
|
||||
const (
|
||||
EnvVarBasicAuthUsername = "BASIC_AUTH_USERNAME"
|
||||
// NOTE: gosec thinks this is a hard-coded password, when in reality it
|
||||
// is the name of an environment variable. We'll suppress that error
|
||||
EnvVarBasicAuthPassword = "BASIC_AUTH_PASSWORD" //nolint:gosec
|
||||
)
|
||||
|
||||
// VinoSpec defines the desired state of Vino
|
||||
type VinoSpec struct {
|
||||
// Define nodelabel parameters
|
||||
|
@ -217,8 +217,10 @@ func (r *VinoReconciler) decorateDaemonSet(ctx context.Context, ds *appsv1.Daemo
|
||||
// TODO develop logic to derive all required ENV variables from VINO CR, and pass them
|
||||
// to setENV function instead
|
||||
if vino.Spec.VMBridge != "" {
|
||||
setEnv(ctx, ds, vino)
|
||||
setEnv(ctx, ds, vinov1.EnvVarVMInterfaceName, vino.Spec.VMBridge)
|
||||
}
|
||||
setEnv(ctx, ds, vinov1.EnvVarBasicAuthUsername, vino.Spec.BMCCredentials.Username)
|
||||
setEnv(ctx, ds, vinov1.EnvVarBasicAuthPassword, vino.Spec.BMCCredentials.Password)
|
||||
|
||||
// this will help avoid colisions if we have two vino CRs in the same namespace
|
||||
ds.Spec.Selector.MatchLabels[vinov1.VinoLabelDSNameSelector] = vino.Name
|
||||
@ -228,30 +230,37 @@ func (r *VinoReconciler) decorateDaemonSet(ctx context.Context, ds *appsv1.Daemo
|
||||
ds.Spec.Template.ObjectMeta.Labels[vinov1.VinoLabelDSNamespaceSelector] = vino.Namespace
|
||||
}
|
||||
|
||||
func setEnv(ctx context.Context, ds *appsv1.DaemonSet, vino *vinov1.Vino) {
|
||||
for i, c := range ds.Spec.Template.Spec.Containers {
|
||||
var set bool
|
||||
for j, envVar := range c.Env {
|
||||
if envVar.Name == vinov1.EnvVarVMInterfaceName {
|
||||
logr.FromContext(ctx).Info("found env variable with vm interface name on daemonset template, overriding it",
|
||||
"vino instance", vino.Namespace+"/"+vino.Name,
|
||||
"container name", c.Name,
|
||||
"value", envVar.Value,
|
||||
)
|
||||
ds.Spec.Template.Spec.Containers[i].Env[j].Value = vino.Spec.VMBridge
|
||||
set = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !set {
|
||||
ds.Spec.Template.Spec.Containers[i].Env = append(
|
||||
ds.Spec.Template.Spec.Containers[i].Env, corev1.EnvVar{
|
||||
Name: vinov1.EnvVarVMInterfaceName,
|
||||
Value: vino.Spec.VMBridge,
|
||||
},
|
||||
// setEnv iterates over all container specs and sets the variable varName to
|
||||
// varValue. If varName already exists for a container, setEnv overrides it
|
||||
func setEnv(ctx context.Context, ds *appsv1.DaemonSet, varName, varValue string) {
|
||||
for i := range ds.Spec.Template.Spec.Containers {
|
||||
setContainerEnv(ctx, &ds.Spec.Template.Spec.Containers[i], varName, varValue)
|
||||
}
|
||||
}
|
||||
|
||||
// setContainerEnv sets the variable varName to varValue for the container. If
|
||||
// varName already exists for the container, setContainerEnv overrides it
|
||||
func setContainerEnv(ctx context.Context, container *corev1.Container, varName, varValue string) {
|
||||
for j, envVar := range container.Env {
|
||||
if envVar.Name == varName {
|
||||
logr.FromContext(ctx).Info("found pre-existing environment variable on daemonset template, overriding it",
|
||||
"container name", container.Name,
|
||||
"environment variable", envVar.Name,
|
||||
"old value", envVar.Value,
|
||||
"new value", varValue,
|
||||
)
|
||||
container.Env[j].Value = varValue
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If we've made it this far, the variable didn't exist.
|
||||
container.Env = append(
|
||||
container.Env, corev1.EnvVar{
|
||||
Name: varName,
|
||||
Value: varValue,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (r *VinoReconciler) waitDaemonSet(ctx context.Context, check dsWaitCondition, ds *appsv1.DaemonSet) error {
|
||||
|
@ -34,23 +34,13 @@ var _ = Describe("Test Setting Env variables", func() {
|
||||
Context("when daemonset is created", func() {
|
||||
l := logr.Discard()
|
||||
ctx := logr.NewContext(context.Background(), l)
|
||||
Context("no containers defined in damonset", func() {
|
||||
It("does nothing", func() {
|
||||
ds := testDS()
|
||||
setEnv(ctx, ds, testVINO())
|
||||
Expect(ds.Spec.Template.Spec.Containers).To(HaveLen(0))
|
||||
})
|
||||
|
||||
})
|
||||
Context("when daemonset has containers", func() {
|
||||
It("sets env interface variable to every container", func() {
|
||||
vino := testVINO()
|
||||
It("sets env variable to every container", func() {
|
||||
ifName := "eth0"
|
||||
vino.Spec.VMBridge = ifName
|
||||
ds := testDS()
|
||||
ds.Spec.Template.Spec.Containers = make([]corev1.Container, 3)
|
||||
|
||||
setEnv(ctx, ds, vino)
|
||||
setEnv(ctx, ds, vinov1.EnvVarVMInterfaceName, ifName)
|
||||
|
||||
for _, container := range ds.Spec.Template.Spec.Containers {
|
||||
Expect(container.Env).To(HaveLen(1))
|
||||
@ -60,24 +50,22 @@ var _ = Describe("Test Setting Env variables", func() {
|
||||
})
|
||||
|
||||
})
|
||||
Context("when daemonset has container with wrong env var values", func() {
|
||||
Context("when daemonset has container with pre-existing env var values", func() {
|
||||
It("overrides that variable in the container", func() {
|
||||
vino := testVINO()
|
||||
ifName := "eth0"
|
||||
vino.Spec.VMBridge = ifName
|
||||
ds := testDS()
|
||||
ds.Spec.Template.Spec.Containers = []corev1.Container{
|
||||
{
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: vinov1.EnvVarVMInterfaceName,
|
||||
Value: "wrong-value",
|
||||
Value: "old-value",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
setEnv(ctx, ds, vino)
|
||||
setEnv(ctx, ds, vinov1.EnvVarVMInterfaceName, ifName)
|
||||
Expect(ds.Spec.Template.Spec.Containers).To(HaveLen(1))
|
||||
container := ds.Spec.Template.Spec.Containers[0]
|
||||
Expect(container.Env).To(HaveLen(1))
|
||||
@ -86,21 +74,19 @@ var _ = Describe("Test Setting Env variables", func() {
|
||||
})
|
||||
})
|
||||
Context("when daemonset containers don't have required variable", func() {
|
||||
It("overrides that variable in the container", func() {
|
||||
vino := testVINO()
|
||||
It("adds that variable to all the containers", func() {
|
||||
ifName := "eth0"
|
||||
vino.Spec.VMBridge = ifName
|
||||
ds := testDS()
|
||||
ds.Spec.Template.Spec.Containers = []corev1.Container{
|
||||
{
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "bar",
|
||||
Value: "wrong-value",
|
||||
Value: "old-value",
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
Value: "wrong-value",
|
||||
Value: "old-value",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -108,17 +94,17 @@ var _ = Describe("Test Setting Env variables", func() {
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "foo",
|
||||
Value: "wrong-value",
|
||||
Value: "old-value",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
Value: "wrong-value",
|
||||
Value: "old-value",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
setEnv(ctx, ds, vino)
|
||||
setEnv(ctx, ds, vinov1.EnvVarVMInterfaceName, ifName)
|
||||
|
||||
Expect(ds.Spec.Template.Spec.Containers).To(HaveLen(2))
|
||||
for _, container := range ds.Spec.Template.Spec.Containers {
|
||||
@ -139,31 +125,28 @@ var _ = Describe("Test Setting Env variables", func() {
|
||||
})
|
||||
Context("when daemonset container has many variables", func() {
|
||||
It("it sets required variable only single time", func() {
|
||||
vino := testVINO()
|
||||
ifName := "eth0"
|
||||
vino.Spec.VMBridge = ifName
|
||||
ds := testDS()
|
||||
ds.Spec.Template.Spec.Containers = []corev1.Container{
|
||||
{
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "foo",
|
||||
Value: "wrong-value",
|
||||
Value: "old-value",
|
||||
},
|
||||
{
|
||||
Name: vinov1.EnvVarVMInterfaceName,
|
||||
Value: "wrong-value",
|
||||
Value: "old-value",
|
||||
},
|
||||
|
||||
{
|
||||
Name: "bar",
|
||||
Value: "wrong-value",
|
||||
Value: "old-value",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
setEnv(ctx, ds, vino)
|
||||
setEnv(ctx, ds, vinov1.EnvVarVMInterfaceName, ifName)
|
||||
Expect(ds.Spec.Template.Spec.Containers).To(HaveLen(1))
|
||||
container := ds.Spec.Template.Spec.Containers[0]
|
||||
Expect(container.Env).To(HaveLen(3))
|
||||
|
Loading…
x
Reference in New Issue
Block a user