mirror of
https://github.com/project-zot/zot.git
synced 2025-01-06 22:40:28 -05:00
336526065f
BREAKING CHANGE: repository paths are now specified under a new config key called "repositories" under "accessControl" section in order to handle "groups" feature. Previously the repository paths were specified directly under "accessControl". This PR adds the ability to create groups of users which can be used for authZ policies, instead of just users. { "http": { "accessControl": { "groups": { Just like the users, groups can be part of repository policies/default policies/admin policies. The 'groups' field in accessControl can be missing if there are no groups. The permissions priority is user>group>default>admin policy, verified in this order (in authz.go), and permissions are cumulative. It works with LDAP too, and the group attribute name is configurable. The DN of the group is used as the group name and the functionality is the same. All groups for the given user are added to the context in authn.go. Repository paths are now specified under a new keyword called "repositories" under "accessControl" section in order to handle "groups" feature. Signed-off-by: Ana-Roberta Lisca <ana.kagome@yahoo.com>
196 lines
4.4 KiB
Go
196 lines
4.4 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/getlantern/deepcopy"
|
|
distspec "github.com/opencontainers/distribution-spec/specs-go"
|
|
|
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
|
"zotregistry.io/zot/pkg/storage"
|
|
)
|
|
|
|
var (
|
|
Commit string //nolint: gochecknoglobals
|
|
ReleaseTag string //nolint: gochecknoglobals
|
|
BinaryType string //nolint: gochecknoglobals
|
|
GoVersion string //nolint: gochecknoglobals
|
|
)
|
|
|
|
type StorageConfig struct {
|
|
RootDirectory string
|
|
Dedupe bool
|
|
RemoteCache bool
|
|
GC bool
|
|
Commit bool
|
|
GCDelay time.Duration
|
|
GCInterval time.Duration
|
|
StorageDriver map[string]interface{} `mapstructure:",omitempty"`
|
|
CacheDriver map[string]interface{} `mapstructure:",omitempty"`
|
|
}
|
|
|
|
type TLSConfig struct {
|
|
Cert string
|
|
Key string
|
|
CACert string
|
|
}
|
|
|
|
type AuthHTPasswd struct {
|
|
Path string
|
|
}
|
|
|
|
type AuthConfig struct {
|
|
FailDelay int
|
|
HTPasswd AuthHTPasswd
|
|
LDAP *LDAPConfig
|
|
Bearer *BearerConfig
|
|
}
|
|
|
|
type BearerConfig struct {
|
|
Realm string
|
|
Service string
|
|
Cert string
|
|
}
|
|
|
|
type MethodRatelimitConfig struct {
|
|
Method string
|
|
Rate int
|
|
}
|
|
|
|
type RatelimitConfig struct {
|
|
Rate *int // requests per second
|
|
Methods []MethodRatelimitConfig `mapstructure:",omitempty"`
|
|
}
|
|
|
|
type HTTPConfig struct {
|
|
Address string
|
|
Port string
|
|
AllowOrigin string // comma separated
|
|
TLS *TLSConfig
|
|
Auth *AuthConfig
|
|
AccessControl *AccessControlConfig
|
|
Realm string
|
|
Ratelimit *RatelimitConfig `mapstructure:",omitempty"`
|
|
}
|
|
|
|
type LDAPConfig struct {
|
|
Port int
|
|
Insecure bool
|
|
StartTLS bool // if !Insecure, then StartTLS or LDAPs
|
|
SkipVerify bool
|
|
SubtreeSearch bool
|
|
Address string
|
|
BindDN string
|
|
UserGroupAttribute string
|
|
BindPassword string
|
|
BaseDN string
|
|
UserAttribute string
|
|
CACert string
|
|
}
|
|
|
|
type LogConfig struct {
|
|
Level string
|
|
Output string
|
|
Audit string
|
|
}
|
|
|
|
type GlobalStorageConfig struct {
|
|
StorageConfig `mapstructure:",squash"`
|
|
SubPaths map[string]StorageConfig
|
|
}
|
|
|
|
type AccessControlConfig struct {
|
|
Repositories Repositories `json:"repositories" mapstructure:"repositories"`
|
|
AdminPolicy Policy
|
|
Groups Groups
|
|
}
|
|
|
|
type (
|
|
Repositories map[string]PolicyGroup
|
|
Groups map[string]Group
|
|
)
|
|
|
|
type Group struct {
|
|
Users []string
|
|
}
|
|
|
|
type PolicyGroup struct {
|
|
Policies []Policy
|
|
DefaultPolicy []string
|
|
AnonymousPolicy []string
|
|
}
|
|
|
|
type Policy struct {
|
|
Users []string
|
|
Actions []string
|
|
Groups []string
|
|
}
|
|
|
|
type Config struct {
|
|
DistSpecVersion string `json:"distSpecVersion" mapstructure:"distSpecVersion"`
|
|
GoVersion string
|
|
Commit string
|
|
ReleaseTag string
|
|
BinaryType string
|
|
Storage GlobalStorageConfig
|
|
HTTP HTTPConfig
|
|
Log *LogConfig
|
|
Extensions *extconf.ExtensionConfig
|
|
}
|
|
|
|
func New() *Config {
|
|
return &Config{
|
|
DistSpecVersion: distspec.Version,
|
|
GoVersion: GoVersion,
|
|
Commit: Commit,
|
|
ReleaseTag: ReleaseTag,
|
|
BinaryType: BinaryType,
|
|
Storage: GlobalStorageConfig{
|
|
StorageConfig: StorageConfig{GC: true, GCDelay: storage.DefaultGCDelay, Dedupe: true},
|
|
},
|
|
HTTP: HTTPConfig{Address: "127.0.0.1", Port: "8080", Auth: &AuthConfig{FailDelay: 0}},
|
|
Log: &LogConfig{Level: "debug"},
|
|
}
|
|
}
|
|
|
|
func (expConfig StorageConfig) ParamsEqual(actConfig StorageConfig) bool {
|
|
return expConfig.GC == actConfig.GC && expConfig.Dedupe == actConfig.Dedupe &&
|
|
expConfig.GCDelay == actConfig.GCDelay && expConfig.GCInterval == actConfig.GCInterval
|
|
}
|
|
|
|
// SameFile compare two files.
|
|
// This method will first do the stat of two file and compare using os.SameFile method.
|
|
func SameFile(str1, str2 string) (bool, error) {
|
|
sFile, err := os.Stat(str1)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
tFile, err := os.Stat(str2)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return os.SameFile(sFile, tFile), nil
|
|
}
|
|
|
|
// Sanitize makes a sanitized copy of the config removing any secrets.
|
|
func (c *Config) Sanitize() *Config {
|
|
sanitizedConfig := &Config{}
|
|
if err := deepcopy.Copy(sanitizedConfig, c); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if c.HTTP.Auth != nil && c.HTTP.Auth.LDAP != nil && c.HTTP.Auth.LDAP.BindPassword != "" {
|
|
sanitizedConfig.HTTP.Auth.LDAP = &LDAPConfig{}
|
|
|
|
if err := deepcopy.Copy(sanitizedConfig.HTTP.Auth.LDAP, c.HTTP.Auth.LDAP); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
sanitizedConfig.HTTP.Auth.LDAP.BindPassword = "******"
|
|
}
|
|
|
|
return sanitizedConfig
|
|
}
|