1
0
mirror of https://github.com/greenpau/caddy-security.git synced 2025-04-18 08:04:02 +03:00

upgrade to github.com/greenpau/go-authcrunch v1.0.10

This commit is contained in:
Paul Greenberg 2022-01-29 14:25:37 -05:00
parent ab4dab5c7a
commit c39eee2098
14 changed files with 336 additions and 131 deletions

View File

@ -81,10 +81,10 @@ module github.com/greenpau/caddy-security
go 1.16
require (
github.com/greenpau/go-authcrunch v1.0.5
github.com/greenpau/go-authcrunch v1.0.10
)
replace github.com/greenpau/go-authcrunch v1.0.5 => /home/greenpau/dev/go/src/github.com/greenpau/go-authcrunch
replace github.com/greenpau/go-authcrunch v1.0.10 => /home/greenpau/dev/go/src/github.com/greenpau/go-authcrunch
```
Then, modify `Makefile` such that that replacement passes to `xcaddy` builder:
@ -93,7 +93,7 @@ Then, modify `Makefile` such that that replacement passes to `xcaddy` builder:
@mkdir -p ../xcaddy-$(PLUGIN_NAME) && cd ../xcaddy-$(PLUGIN_NAME) && \
xcaddy build $(CADDY_VERSION) --output ../$(PLUGIN_NAME)/bin/caddy \
--with github.com/greenpau/caddy-security@$(LATEST_GIT_COMMIT)=$(BUILD_DIR) \
--with github.com/greenpau/go-authcrunch@v1.0.5=/home/greenpau/dev/go/src/github.com/greenpau/go-authcrunch
--with github.com/greenpau/go-authcrunch@v1.0.10=/home/greenpau/dev/go/src/github.com/greenpau/go-authcrunch
```
Once all the necessary packages are installed, you should be ready to compile

View File

@ -16,7 +16,7 @@ all: info
@mkdir -p ../xcaddy-$(PLUGIN_NAME) && cd ../xcaddy-$(PLUGIN_NAME) && \
xcaddy build $(CADDY_VERSION) --output ../$(PLUGIN_NAME)/bin/caddy \
--with github.com/greenpau/caddy-security@$(LATEST_GIT_COMMIT)=$(BUILD_DIR)
@#--with github.com/greenpau/go-authcrunch@v1.0.9=/home/greenpau/dev/go/src/github.com/greenpau/go-authcrunch
@#--with github.com/greenpau/go-authcrunch@v1.0.10=/home/greenpau/dev/go/src/github.com/greenpau/go-authcrunch
@#--with github.com/greenpau/caddy-trace@v1.1.8=/home/greenpau/dev/go/src/github.com/greenpau/caddy-trace
@#bin/caddy run -config assets/config/Caddyfile
@for f in `find ./assets -type f -name 'Caddyfile'`; do bin/caddy fmt -overwrite $$f; done
@ -69,8 +69,9 @@ qtest: covdir
@#time richgo test -v -coverprofile=.coverage/coverage.out -run TestApp ./*.go
@#time richgo test -v -coverprofile=.coverage/coverage.out -run TestParseCaddyfileAppConfig ./*.go
@#time richgo test -v -coverprofile=.coverage/coverage.out -run TestParseCaddyfileCredentials ./*.go
@time richgo test -v -coverprofile=.coverage/coverage.out -run TestParseCaddyfileMessaging ./*.go
@#time richgo test -v -coverprofile=.coverage/coverage.out -run TestParseCaddyfileAuthentication ./*.go
@time richgo test -v -coverprofile=.coverage/coverage.out -run TestParseCaddyfileAuthorization ./*.go
@#time richgo test -v -coverprofile=.coverage/coverage.out -run TestParseCaddyfileAuthorization ./*.go
@#go test -v -coverprofile=.coverage/coverage.out -run TestParseCaddyfile ./*.go
@#go test -v -coverprofile=.coverage/coverage.out -run Test* ./pkg/services/...
@go tool cover -html=.coverage/coverage.out -o .coverage/coverage.html

View File

@ -40,6 +40,7 @@ Please see other plugins:
* [Overview](#overview)
* [Getting Started](#getting-started)
* [Credentials](#credentials)
* [Messaging](#messaging)
* [Authentication](#authentication)
* [Authorization](#authorization)
* [User Interface](#user-interface)
@ -82,14 +83,13 @@ Download Caddy with the plugins enabled:
### Credentials
The following configuration adds SMTP credentials to security app.
Subsequently, the app and plugin will be able to use the credentials.
Subsequently, the app and plugin will be able to use the credentials
in its messaging configuration.
```
{
security {
credentials email smtp.outlook.com {
address outlook.office365.com:993
protocol smtp
credentials smtp.outlook.com {
username {env.SMTP_USERNAME}
password {env.SMTP_PASSWORD}
}
@ -97,6 +97,23 @@ Subsequently, the app and plugin will be able to use the credentials.
}
```
### Messaging
The following configuration sets up email messaging provider. It will use
the previously configured `smtp.outlook.com` credentials.
```
{
security {
messaging email provider smtp.outlook.com {
address outlook.office365.com:25
protocol smtp
credentials smtp.outlook.com
}
}
}
```
### Authentication
The following configuration adds authentication portal.

View File

@ -5,11 +5,10 @@
https_port 8443
security {
credentials email smtp.contoso.com {
address smtp.contoso.com:993
protocol smtp
credentials smtp.contoso.com {
username foo
password bar
domain contoso.com
}
authentication portal myportal {

View File

@ -1,57 +0,0 @@
{
http_port 8080
https_port 8443
debug
security {
authentication portal myportal {
crypto default token lifetime 3600
crypto key sign-verify a3c6eeee16e4479e9f31786e30b3ebdc
backends {
jumpcloud_saml_backend {
method saml
realm jumpcloud
provider generic
idp_metadata_location /home/greenpau/tmp/authp/cloudjump/JumpCloud-saml2-metadata.xml
idp_sign_cert_location /home/greenpau/tmp/authp/cloudjump/certificate.pem
idp_login_url https://sso.jumpcloud.com/saml2/auth-portal-saml
application_name "MyFIOS Auth Portal"
entity_id "urn:auth-portal"
acs_url https://auth.myfiosgateway.com:8443/saml/jumpcloud
}
}
cookie domain myfiosgateway.com
ui {
links {
"My Website" https://assetq.myfiosgateway.com:8443/ icon "las la-star"
"My Identity" "/whoami" icon "las la-user"
}
}
transform user {
match origin jumpcloud
action add role authp/user
}
}
authorization policy mypolicy {
set auth url https://auth.myfiosgateway.com:8443/
allow roles authp/admin authp/user
crypto key verify a3c6eeee16e4479e9f31786e30b3ebdc
}
}
}
auth.myfiosgateway.com {
tls /home/greenpau/.local/tls/myfiosgateway/server.crt /home/greenpau/.local/tls/myfiosgateway/server.key
route {
authenticate * with myportal
}
}
assetq.myfiosgateway.com {
tls /home/greenpau/.local/tls/myfiosgateway/server.crt /home/greenpau/.local/tls/myfiosgateway/server.key
route {
authorize with mypolicy
respond "assetq is running"
}
}

View File

@ -0,0 +1,12 @@
#!/bin/bash
set -e
printf "Updating doc references\n"
ACV=`cat ../go-authcrunch/VERSION | head -1`
echo "go-authcrunch v${ACV}"
sed -i 's/go-authcrunch v[0-9]\.[0-9]*\.[0-9]*/go-authcrunch v'"${ACV}"'/' CONTRIBUTING.md
sed -i 's/go-authcrunch@v[0-9]\.[0-9]*\.[0-9]*/go-authcrunch@v'"${ACV}"'/' CONTRIBUTING.md
sed -i 's/go-authcrunch@v[0-9]\.[0-9]*\.[0-9]*/go-authcrunch@v'"${ACV}"'/' Makefile
sed -i 's/go-authcrunch v[0-9]\.[0-9]*\.[0-9]*/go-authcrunch v'"${ACV}"'/' go.mod

View File

@ -56,6 +56,10 @@ func parseCaddyfile(d *caddyfile.Dispenser, _ interface{}) (interface{}, error)
if err := parseCaddyfileCredentials(d, repl, app.Config); err != nil {
return nil, err
}
case "messaging":
if err := parseCaddyfileMessaging(d, repl, app.Config); err != nil {
return nil, err
}
case "authentication":
if err := parseCaddyfileAuthentication(d, repl, app.Config); err != nil {
return nil, err

View File

@ -31,42 +31,34 @@ const (
//
// Syntax:
//
// credentials email <label> {
// address <uri>
// protocol <smtp|pop3|imap>
// credentials <label> {
// username <username>
// password <password>
// domain <name>
// }
//
func parseCaddyfileCredentials(d *caddyfile.Dispenser, repl *caddy.Replacer, cfg *authcrunch.Config) error {
args := util.FindReplaceAll(repl, d.RemainingArgs())
if len(args) != 2 {
if len(args) != 1 {
return d.ArgErr()
}
switch args[0] {
case "email":
c := &credentials.SMTP{Name: args[1]}
for nesting := d.Nesting(); d.NextBlock(nesting); {
k := d.Val()
v := util.FindReplaceAll(repl, d.RemainingArgs())
switch k {
case "address":
c.Address = v[0]
case "protocol":
c.Protocol = v[0]
case "username":
c.Username = v[0]
case "password":
c.Password = v[0]
default:
return errors.ErrMalformedDirective.WithArgs([]string{credPrefix, args[0], k}, v)
}
c := &credentials.Generic{Name: args[0]}
for nesting := d.Nesting(); d.NextBlock(nesting); {
k := d.Val()
v := util.FindReplaceAll(repl, d.RemainingArgs())
switch k {
case "domain":
c.Domain = v[0]
case "username":
c.Username = v[0]
case "password":
c.Password = v[0]
default:
return errors.ErrMalformedDirective.WithArgs([]string{credPrefix, args[0], k}, v)
}
if err := cfg.AddCredential(c); err != nil {
return errors.ErrMalformedDirective.WithArgs([]string{credPrefix, args[0], args[1]}, err)
}
default:
return errors.ErrMalformedDirective.WithArgs(credPrefix, args)
}
if err := cfg.AddCredential(c); err != nil {
return errors.ErrMalformedDirective.WithArgs([]string{credPrefix, args[0]}, err)
}
return nil
}

View File

@ -36,85 +36,102 @@ func TestParseCaddyfileCredentials(t *testing.T) {
name: "test valid smtp credentials",
d: caddyfile.NewTestDispenser(`
security {
credentials email smtp.contoso.com {
address smtp.contoso.com:993
protocol smtp
username foo
password bar
credentials smtp.contoso.com {
username foo
password bar
}
}`),
want: `{
"config": {
"credentials": {
"email": [
"generic": [
{
"address": "smtp.contoso.com:993",
"name": "smtp.contoso.com",
"username": "foo",
"password": "bar",
"protocol": "smtp"
"password": "bar"
}
]
}
}
}`,
},
{
name: "test valid smtp credentials with optional domain",
d: caddyfile.NewTestDispenser(`
security {
credentials smtp.contoso.com {
username foo
password bar
domain contoso.com
}
}`),
want: `{
"config": {
"credentials": {
"generic": [
{
"name": "smtp.contoso.com",
"username": "foo",
"password": "bar",
"domain": "contoso.com"
}
]
}
}
}`,
},
{
name: "test malformed credentials definition",
d: caddyfile.NewTestDispenser(`
security {
credentials email smtp.contoso.com foo {
credentials smtp.contoso.com foo {
username foo
password bar
}
}`),
shouldErr: true,
err: fmt.Errorf("%s:%d - Error during parsing: Wrong argument count or unexpected line ending after '%s'", tf, 3, "foo"),
err: fmt.Errorf("%s:%d - Error during parsing: Wrong argument count or unexpected line ending after 'foo'", tf, 3),
},
{
name: "test unsupported credentials keyword",
d: caddyfile.NewTestDispenser(`
security {
credentials email smtp.contoso.com {
credentials smtp.contoso.com {
foo bar
}
}`),
shouldErr: true,
err: errors.ErrMalformedDirective.WithArgs(
[]string{credPrefix, "email", "foo"},
[]string{credPrefix, "smtp.contoso.com", "foo"},
[]string{"bar"},
),
},
{
name: "test smtp credentials without address",
name: "test smtp credentials without username",
d: caddyfile.NewTestDispenser(`
security {
credentials email smtp.contoso.com {
protocol smtp
username foo
credentials smtp.contoso.com {
password bar
}
}`),
shouldErr: true,
err: errors.ErrMalformedDirective.WithArgs(
[]string{credPrefix, "email", "smtp.contoso.com"},
errors.ErrCredKeyValueEmpty.WithArgs("address"),
[]string{credPrefix, "smtp.contoso.com"},
errors.ErrCredKeyValueEmpty.WithArgs("username"),
),
},
{
name: "test unsupported credentials type",
name: "test smtp credentials without password",
d: caddyfile.NewTestDispenser(`
security {
credentials foo bar {
protocol smtp
credentials smtp.contoso.com {
username foo
password bar
}
}`),
shouldErr: true,
err: errors.ErrMalformedDirective.WithArgs(
credPrefix,
[]string{"foo", "bar"},
[]string{credPrefix, "smtp.contoso.com"},
errors.ErrCredKeyValueEmpty.WithArgs("password"),
),
},
}

91
caddyfile_messaging.go Normal file
View File

@ -0,0 +1,91 @@
// Copyright 2022 Paul Greenberg greenpau@outlook.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package security
import (
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"github.com/greenpau/caddy-security/pkg/util"
"github.com/greenpau/go-authcrunch"
"github.com/greenpau/go-authcrunch/pkg/errors"
"github.com/greenpau/go-authcrunch/pkg/messaging"
)
const (
msgPrefix = "security.messaging"
)
// parseCaddyfileCredentials parses messaging configuration.
//
// Syntax:
//
// messaging email provider <name> {
// address <address>
// protocol smtp
// credentials <credential_name>
// sender <email_address> [name]
// template password_recovery <path>
// template registration_confirmation <path>
// template registration_verdict <path>
// template mfa_otp <path>
// }
//
func parseCaddyfileMessaging(d *caddyfile.Dispenser, repl *caddy.Replacer, cfg *authcrunch.Config) error {
args := util.FindReplaceAll(repl, d.RemainingArgs())
if len(args) != 3 {
return d.ArgErr()
}
if args[1] != "provider" {
return d.ArgErr()
}
switch args[0] {
case "email":
c := &messaging.EmailProvider{Name: args[1]}
for nesting := d.Nesting(); d.NextBlock(nesting); {
k := d.Val()
v := util.FindReplaceAll(repl, d.RemainingArgs())
switch k {
case "address":
c.Address = v[0]
case "protocol":
c.Protocol = v[0]
case "credentials":
c.Credentials = v[0]
case "sender":
c.SenderEmail = v[0]
if len(v) > 1 {
c.SenderName = v[1]
}
case "template":
if len(v) != 2 {
return errors.ErrMalformedDirective.WithArgs([]string{msgPrefix, args[0], k}, v)
}
if c.Templates == nil {
c.Templates = make(map[string]string)
}
c.Templates[v[0]] = v[1]
default:
return errors.ErrMalformedDirective.WithArgs([]string{msgPrefix, args[0], k}, v)
}
}
if err := cfg.AddMessagingProvider(c); err != nil {
return errors.ErrMalformedDirective.WithArgs([]string{msgPrefix, args[0], args[1]}, err)
}
default:
return errors.ErrMalformedDirective.WithArgs(msgPrefix, args)
}
return nil
}

133
caddyfile_messaging_test.go Normal file
View File

@ -0,0 +1,133 @@
// Copyright 2022 Paul Greenberg greenpau@outlook.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package security
import (
"fmt"
"testing"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
"github.com/google/go-cmp/cmp"
"github.com/greenpau/go-authcrunch/pkg/errors"
)
func TestParseCaddyfileMessaging(t *testing.T) {
testcases := []struct {
name string
d *caddyfile.Dispenser
want string
shouldErr bool
err error
}{
{
name: "test valid email provider with credentials",
d: caddyfile.NewTestDispenser(`
security {
credentials root@localhost {
username root
password foobar
}
messaging email provider local_smtp_server {
address localhost:25
protocol smtp
credentials root@localhost
sender root@localhost "Auth Portal"
template password_recovery path/to/password_recovery.tmpl
template registration_confirmation path/to/registration_confirmation.tmpl
template registration_verdict path/to/registration_verdict.tmpl
template mfa_otp path/to/mfa_otp.tmpl
}`),
want: `{
"config": {
"credentials": {
"generic": [
{
"name": "root@localhost",
"username": "root",
"password": "foobar"
}
]
},
"messaging": {
"email_providers": [
{
"name": "provider",
"address": "localhost:25",
"protocol": "smtp",
"credentials": "root@localhost",
"sender_email": "root@localhost",
"sender_name": "Auth Portal",
"templates": {
"mfa_otp": "path/to/mfa_otp.tmpl",
"password_recovery": "path/to/password_recovery.tmpl",
"registration_confirmation": "path/to/registration_confirmation.tmpl",
"registration_verdict": "path/to/registration_verdict.tmpl"
}
}
]
}
}
}`,
},
{
name: "test malformed email provider definition",
d: caddyfile.NewTestDispenser(`
security {
messaging email provider local_smtp_server foo {
address localhost:25
}
}`),
shouldErr: true,
err: fmt.Errorf("%s:%d - Error during parsing: Wrong argument count or unexpected line ending after 'foo'", tf, 3),
},
{
name: "test malformed non-email provider definition",
d: caddyfile.NewTestDispenser(`
security {
messaging bar provider local_smtp_server {
address localhost:25
}
}`),
shouldErr: true,
err: errors.ErrMalformedDirective.WithArgs(msgPrefix, []string{"bar", "provider", "local_smtp_server"}),
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
app, err := parseCaddyfile(tc.d, nil)
if err != nil {
if !tc.shouldErr {
t.Fatalf("expected success, got: %v", err)
}
if diff := cmp.Diff(err.Error(), tc.err.Error()); diff != "" {
t.Fatalf("unexpected error: %v, want: %v", err, tc.err)
}
return
}
if tc.shouldErr {
t.Fatalf("unexpected success, want: %v", tc.err)
}
got := unpack(t, string(app.(httpcaddyfile.App).Value))
want := unpack(t, tc.want)
if diff := cmp.Diff(want, got); diff != "" {
t.Logf("JSON: %v", string(app.(httpcaddyfile.App).Value))
t.Errorf("parseCaddyfileMessaging() mismatch (-want +got):\n%s", diff)
}
})
}
}

View File

@ -37,9 +37,7 @@ func TestParseCaddyfileAppConfig(t *testing.T) {
name: "test email credentials",
d: caddyfile.NewTestDispenser(`
security {
credentials email smtp.contoso.com {
address smtp.contoso.com:993
protocol smtp
credentials smtp.contoso.com {
username foo
password bar
}
@ -47,13 +45,11 @@ func TestParseCaddyfileAppConfig(t *testing.T) {
want: `{
"config": {
"credentials": {
"email": [
"generic": [
{
"address": "smtp.contoso.com:993",
"name": "smtp.contoso.com",
"username": "foo",
"password": "bar",
"protocol": "smtp"
"password": "bar"
}
]
}

2
go.mod
View File

@ -5,7 +5,7 @@ go 1.16
require (
github.com/caddyserver/caddy/v2 v2.4.6
github.com/google/go-cmp v0.5.7
github.com/greenpau/go-authcrunch v1.0.9
github.com/greenpau/go-authcrunch v1.0.10
github.com/satori/go.uuid v1.2.0
go.uber.org/zap v1.20.0
)

4
go.sum
View File

@ -471,8 +471,8 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/greenpau/go-authcrunch v1.0.9 h1:8upZTqfZ0FGT8fZt47wZqgI1bxcLNW2MFGY//kQUObA=
github.com/greenpau/go-authcrunch v1.0.9/go.mod h1:guuktZjZUnHdP5pZ7D164GtiqKF1s1rlL99GR107XJk=
github.com/greenpau/go-authcrunch v1.0.10 h1:hV3rxfj7gcOKRxbL3MR3+w9dSb5hrmDAu/eE0CkUAnc=
github.com/greenpau/go-authcrunch v1.0.10/go.mod h1:guuktZjZUnHdP5pZ7D164GtiqKF1s1rlL99GR107XJk=
github.com/greenpau/versioned v1.0.27 h1:aFJ16tzsUkbc6WT7DRia60S0VrgWzBNuul3h0RXFKxM=
github.com/greenpau/versioned v1.0.27/go.mod h1:rtFCvaWWNbMH4CJnje/xicgmrM63j++rUh5juSu0k/A=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=