blob: 07a4103270cb3313bf46f71ea8a427da76e2bf82 [file] [log] [blame]
// Copyright Istio Authors
//
// 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 model
import (
"fmt"
"strings"
)
import (
rbacpb "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3"
)
import (
"github.com/apache/dubbo-go-pixiu/pilot/pkg/security/authz/matcher"
sm "github.com/apache/dubbo-go-pixiu/pilot/pkg/security/model"
"github.com/apache/dubbo-go-pixiu/pkg/spiffe"
)
type generator interface {
permission(key, value string, forTCP bool) (*rbacpb.Permission, error)
principal(key, value string, forTCP bool) (*rbacpb.Principal, error)
}
type destIPGenerator struct{}
func (destIPGenerator) permission(_, value string, _ bool) (*rbacpb.Permission, error) {
cidrRange, err := matcher.CidrRange(value)
if err != nil {
return nil, err
}
return permissionDestinationIP(cidrRange), nil
}
func (destIPGenerator) principal(_, _ string, _ bool) (*rbacpb.Principal, error) {
return nil, fmt.Errorf("unimplemented")
}
type destPortGenerator struct{}
func (destPortGenerator) permission(_, value string, _ bool) (*rbacpb.Permission, error) {
portValue, err := convertToPort(value)
if err != nil {
return nil, err
}
return permissionDestinationPort(portValue), nil
}
func (destPortGenerator) principal(_, _ string, _ bool) (*rbacpb.Principal, error) {
return nil, fmt.Errorf("unimplemented")
}
type connSNIGenerator struct{}
func (connSNIGenerator) permission(_, value string, _ bool) (*rbacpb.Permission, error) {
m := matcher.StringMatcher(value)
return permissionRequestedServerName(m), nil
}
func (connSNIGenerator) principal(_, _ string, _ bool) (*rbacpb.Principal, error) {
return nil, fmt.Errorf("unimplemented")
}
type envoyFilterGenerator struct{}
func (envoyFilterGenerator) permission(key, value string, _ bool) (*rbacpb.Permission, error) {
// Split key of format "experimental.envoy.filters.a.b[c]" to "envoy.filters.a.b" and "c".
parts := strings.SplitN(strings.TrimSuffix(strings.TrimPrefix(key, "experimental."), "]"), "[", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("invalid key: %v", key)
}
// If value is of format [v], create a list matcher.
// Else, if value is of format v, create a string matcher.
if strings.HasPrefix(value, "[") && strings.HasSuffix(value, "]") {
m := matcher.MetadataListMatcher(parts[0], parts[1:], matcher.StringMatcher(strings.Trim(value, "[]")))
return permissionMetadata(m), nil
}
m := matcher.MetadataStringMatcher(parts[0], parts[1], matcher.StringMatcher(value))
return permissionMetadata(m), nil
}
func (envoyFilterGenerator) principal(_, _ string, _ bool) (*rbacpb.Principal, error) {
return nil, fmt.Errorf("unimplemented")
}
type srcIPGenerator struct{}
func (srcIPGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) {
return nil, fmt.Errorf("unimplemented")
}
func (srcIPGenerator) principal(_, value string, _ bool) (*rbacpb.Principal, error) {
cidr, err := matcher.CidrRange(value)
if err != nil {
return nil, err
}
return principalDirectRemoteIP(cidr), nil
}
type remoteIPGenerator struct{}
func (remoteIPGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) {
return nil, fmt.Errorf("unimplemented")
}
func (remoteIPGenerator) principal(_, value string, _ bool) (*rbacpb.Principal, error) {
cidr, err := matcher.CidrRange(value)
if err != nil {
return nil, err
}
return principalRemoteIP(cidr), nil
}
type srcNamespaceGenerator struct{}
func (srcNamespaceGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) {
return nil, fmt.Errorf("unimplemented")
}
func (srcNamespaceGenerator) principal(_, value string, _ bool) (*rbacpb.Principal, error) {
v := strings.Replace(value, "*", ".*", -1)
m := matcher.StringMatcherRegex(fmt.Sprintf(".*/ns/%s/.*", v))
return principalAuthenticated(m), nil
}
type srcPrincipalGenerator struct{}
func (srcPrincipalGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) {
return nil, fmt.Errorf("unimplemented")
}
func (srcPrincipalGenerator) principal(key, value string, _ bool) (*rbacpb.Principal, error) {
m := matcher.StringMatcherWithPrefix(value, spiffe.URIPrefix)
return principalAuthenticated(m), nil
}
type requestPrincipalGenerator struct{}
func (requestPrincipalGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) {
return nil, fmt.Errorf("unimplemented")
}
func (requestPrincipalGenerator) principal(key, value string, forTCP bool) (*rbacpb.Principal, error) {
if forTCP {
return nil, fmt.Errorf("%q is HTTP only", key)
}
m := matcher.MetadataStringMatcher(sm.AuthnFilterName, key, matcher.StringMatcher(value))
return principalMetadata(m), nil
}
type requestAudiencesGenerator struct{}
func (requestAudiencesGenerator) permission(key, value string, forTCP bool) (*rbacpb.Permission, error) {
return requestPrincipalGenerator{}.permission(key, value, forTCP)
}
func (requestAudiencesGenerator) principal(key, value string, forTCP bool) (*rbacpb.Principal, error) {
return requestPrincipalGenerator{}.principal(key, value, forTCP)
}
type requestPresenterGenerator struct{}
func (requestPresenterGenerator) permission(key, value string, forTCP bool) (*rbacpb.Permission, error) {
return requestPrincipalGenerator{}.permission(key, value, forTCP)
}
func (requestPresenterGenerator) principal(key, value string, forTCP bool) (*rbacpb.Principal, error) {
return requestPrincipalGenerator{}.principal(key, value, forTCP)
}
type requestHeaderGenerator struct{}
func (requestHeaderGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) {
return nil, fmt.Errorf("unimplemented")
}
func (requestHeaderGenerator) principal(key, value string, forTCP bool) (*rbacpb.Principal, error) {
if forTCP {
return nil, fmt.Errorf("%q is HTTP only", key)
}
header, err := extractNameInBrackets(strings.TrimPrefix(key, attrRequestHeader))
if err != nil {
return nil, err
}
m := matcher.HeaderMatcher(header, value)
return principalHeader(m), nil
}
type requestClaimGenerator struct{}
func (requestClaimGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) {
return nil, fmt.Errorf("unimplemented")
}
func (requestClaimGenerator) principal(key, value string, forTCP bool) (*rbacpb.Principal, error) {
if forTCP {
return nil, fmt.Errorf("%q is HTTP only", key)
}
claims, err := extractNameInNestedBrackets(strings.TrimPrefix(key, attrRequestClaims))
if err != nil {
return nil, err
}
// Generate a metadata list matcher for the given path keys and value.
// On proxy side, the value should be of list type.
m := MetadataMatcherForJWTClaims(claims, matcher.StringMatcher(value))
return principalMetadata(m), nil
}
type hostGenerator struct{}
func (hg hostGenerator) permission(key, value string, forTCP bool) (*rbacpb.Permission, error) {
if forTCP {
return nil, fmt.Errorf("%q is HTTP only", key)
}
return permissionHeader(matcher.HostMatcher(hostHeader, value)), nil
}
func (hostGenerator) principal(key, value string, forTCP bool) (*rbacpb.Principal, error) {
return nil, fmt.Errorf("unimplemented")
}
type pathGenerator struct{}
func (g pathGenerator) permission(key, value string, forTCP bool) (*rbacpb.Permission, error) {
if forTCP {
return nil, fmt.Errorf("%q is HTTP only", key)
}
m := matcher.PathMatcher(value)
return permissionPath(m), nil
}
func (pathGenerator) principal(key, value string, forTCP bool) (*rbacpb.Principal, error) {
return nil, fmt.Errorf("unimplemented")
}
type methodGenerator struct{}
func (methodGenerator) permission(key, value string, forTCP bool) (*rbacpb.Permission, error) {
if forTCP {
return nil, fmt.Errorf("%q is HTTP only", key)
}
m := matcher.HeaderMatcher(methodHeader, value)
return permissionHeader(m), nil
}
func (methodGenerator) principal(key, value string, forTCP bool) (*rbacpb.Principal, error) {
return nil, fmt.Errorf("unimplemented")
}