authorize: add authorization (#59)

* authorize: authorization module adds support for per-route access policy. In this release we support the most common forms of identity based access policy: `allowed_users`, `allowed_groups`, and `allowed_domains`. In future versions, the authorization module will also support context and device based authorization policy and decisions. See website documentation for more details.
 * docs: updated `env.example` to include a `POLICY` setting example.
 * docs:  added `IDP_SERVICE_ACCOUNT` to  `env.example` .
 * docs: removed `PROXY_ROOT_DOMAIN` settings which has been replaced by `POLICY`.
 * all: removed `ALLOWED_DOMAINS` settings which has been replaced by `POLICY`. Authorization is now handled by the authorization service and is defined in the policy configuration files.
 * proxy: `ROUTES` settings which has been replaced by `POLICY`.
* internal/log: `http.Server` and `httputil.NewSingleHostReverseProxy` now uses pomerium's logging package instead of the standard library's built in one.

Closes #54
Closes #41
Closes #61
Closes #58
This commit is contained in:
Bobby DeSimone 2019-03-07 12:47:07 -08:00 committed by GitHub
parent 1187be2bf3
commit c13459bb88
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
65 changed files with 1683 additions and 879 deletions

83
internal/policy/policy.go Normal file
View file

@ -0,0 +1,83 @@
package policy // import "github.com/pomerium/pomerium/internal/policy"
import (
"fmt"
"io/ioutil"
"net/url"
"strings"
"time"
"github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/internal/fileutil"
yaml "gopkg.in/yaml.v2"
)
// Policy contains authorization policy information.
// todo(bdd) : add upstream timeout and configuration settings
type Policy struct {
// proxy related
From string `yaml:"from"`
To string `yaml:"to"`
// upstream transport settings
UpstreamTimeout time.Duration `yaml:"timeout"`
// Identity related policy
AllowedEmails []string `yaml:"allowed_users"`
AllowedGroups []string `yaml:"allowed_groups"`
AllowedDomains []string `yaml:"allowed_domains"`
Source *url.URL
Destination *url.URL
}
func (p *Policy) validate() (err error) {
p.Source, err = urlParse(p.From)
if err != nil {
return err
}
p.Destination, err = urlParse(p.To)
if err != nil {
return err
}
return nil
}
// FromConfig parses configuration file as bytes and returns authorization
// policies. Supports yaml, json.
func FromConfig(confBytes []byte) ([]Policy, error) {
var f []Policy
if err := yaml.Unmarshal(confBytes, &f); err != nil {
return nil, err
}
// build source and destination urls
for i := range f {
if err := (&f[i]).validate(); err != nil {
return nil, err
}
}
log.Info().Msgf("from config %+v", f)
return f, nil
}
// FromConfigFile parses configuration file from a path and returns
// authorization policies. Supports yaml, json.
func FromConfigFile(f string) ([]Policy, error) {
exists, err := fileutil.IsReadableFile(f)
if err != nil || !exists {
return nil, fmt.Errorf("policy file %v: %v exists? %v", f, err, exists)
}
confBytes, err := ioutil.ReadFile(f)
if err != nil {
return nil, err
}
return FromConfig(confBytes)
}
// urlParse wraps url.Parse to add a scheme if none-exists.
// https://github.com/golang/go/issues/12585
func urlParse(uri string) (*url.URL, error) {
if !strings.Contains(uri, "://") {
uri = fmt.Sprintf("https://%s", uri)
}
return url.ParseRequestURI(uri)
}