Add annotation to support map of user/pass pairs in basic auth

This commit is contained in:
A Gardner 2019-09-13 10:59:32 -04:00
parent 55820ef1e8
commit 376b862c23
4 changed files with 147 additions and 20 deletions

View file

@ -20,6 +20,7 @@ import (
"fmt"
"io/ioutil"
"regexp"
"strings"
"github.com/pkg/errors"
api "k8s.io/api/core/v1"
@ -41,12 +42,13 @@ var (
// Config returns authentication configuration for an Ingress rule
type Config struct {
Type string `json:"type"`
Realm string `json:"realm"`
File string `json:"file"`
Secured bool `json:"secured"`
FileSHA string `json:"fileSha"`
Secret string `json:"secret"`
Type string `json:"type"`
Realm string `json:"realm"`
File string `json:"file"`
Secured bool `json:"secured"`
FileSHA string `json:"fileSha"`
Secret string `json:"secret"`
SecretType string `json:"secretType"`
}
// Equal tests for equality between two Config types
@ -102,6 +104,12 @@ func (a auth) Parse(ing *networking.Ingress) (interface{}, error) {
return nil, ing_errors.NewLocationDenied("invalid authentication type")
}
var secretType string
secretType, err = parser.GetStringAnnotation("auth-secret-type", ing)
if err != nil {
secretType = "auth-file"
}
s, err := parser.GetStringAnnotation("auth-secret", ing)
if err != nil {
return nil, ing_errors.LocationDenied{
@ -131,24 +139,37 @@ func (a auth) Parse(ing *networking.Ingress) (interface{}, error) {
realm, _ := parser.GetStringAnnotation("auth-realm", ing)
passFile := fmt.Sprintf("%v/%v-%v.passwd", a.authDirectory, ing.GetNamespace(), ing.GetName())
err = dumpSecret(passFile, secret)
if err != nil {
return nil, err
if secretType == "auth-file" {
err = dumpSecretAuthFile(passFile, secret)
if err != nil {
return nil, err
}
} else if secretType == "auth-map" {
err = dumpSecretAuthMap(passFile, secret)
if err != nil {
return nil, err
}
} else {
return nil, ing_errors.LocationDenied{
Reason: errors.Wrap(err, "invalid auth-secret-type in annotation, must be 'auth-file' or 'auth-map'"),
}
}
return &Config{
Type: at,
Realm: realm,
File: passFile,
Secured: true,
FileSHA: file.SHA1(passFile),
Secret: name,
Type: at,
Realm: realm,
File: passFile,
Secured: true,
FileSHA: file.SHA1(passFile),
Secret: name,
SecretType: secretType,
}, nil
}
// dumpSecret dumps the content of a secret into a file
// in the expected format for the specified authorization
func dumpSecret(filename string, secret *api.Secret) error {
func dumpSecretAuthFile(filename string, secret *api.Secret) error {
val, ok := secret.Data["auth"]
if !ok {
return ing_errors.LocationDenied{
@ -165,3 +186,22 @@ func dumpSecret(filename string, secret *api.Secret) error {
return nil
}
func dumpSecretAuthMap(filename string, secret *api.Secret) error {
builder := &strings.Builder{}
for user, pass := range secret.Data {
builder.WriteString(user)
builder.WriteString(":")
builder.WriteString(string(pass))
builder.WriteString("\n")
}
err := ioutil.WriteFile(filename, []byte(builder.String()), file.ReadWriteByUser)
if err != nil {
return ing_errors.LocationDenied{
Reason: errors.Wrap(err, "unexpected error creating password file"),
}
}
return nil
}