Skip to content

Commit

Permalink
Fix initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dudyas6 committed Nov 11, 2024
1 parent b86a302 commit 28eb660
Show file tree
Hide file tree
Showing 21 changed files with 151 additions and 25 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ DISABLED_HOST_VALIDATIONS := $(or ${DISABLED_HOST_VALIDATIONS}, "")
DISABLED_STEPS := $(or ${DISABLED_STEPS}, "")
DISABLE_TLS := $(or ${DISABLE_TLS},false)
ENABLE_ORG_TENANCY := $(or ${ENABLE_ORG_TENANCY},False)
ENABLE_OCM_AUTHZ := $(or ${ENABLE_OCM_AUTHZ},False)
ALLOW_CONVERGED_FLOW := $(or ${ALLOW_CONVERGED_FLOW}, false)
ENABLE_ORG_BASED_FEATURE_GATES := $(or ${ENABLE_ORG_BASED_FEATURE_GATES},False)
KIND_EXPERIMENTAL_PROVIDER=podman
Expand Down Expand Up @@ -338,7 +339,7 @@ deploy-service-requirements: | deploy-namespace deploy-inventory-service-file
--storage $(STORAGE) --ipv6-support $(IPV6_SUPPORT) --enable-sno-dnsmasq $(ENABLE_SINGLE_NODE_DNSMASQ) \
--disk-encryption-support $(DISK_ENCRYPTION_SUPPORT) --hw-requirements '$(subst ",\",$(HW_REQUIREMENTS))' \
--disabled-host-validations "$(DISABLED_HOST_VALIDATIONS)" --disabled-steps "$(DISABLED_STEPS)" \
--enable-org-tenancy $(ENABLE_ORG_TENANCY) \
--enable-org-tenancy $(ENABLE_ORG_TENANCY) --enable-ocm-authz $(ENABLE_OCM_AUTHZ)\
--enable-org-based-feature-gate $(ENABLE_ORG_BASED_FEATURE_GATES) $(ALLOW_CONVERGED_FLOW_CMD) $(DISABLE_TLS_CMD)
ifeq ($(MIRROR_REGISTRY_SUPPORT), True)
python3 ./tools/deploy_assisted_installer_configmap_registry_ca.py --target "$(TARGET)" \
Expand Down
18 changes: 14 additions & 4 deletions internal/bminventory/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3064,6 +3064,7 @@ func (b *bareMetalInventory) listClustersInternal(ctx context.Context, params in

var dbClusters []*common.Cluster
var clusters []*models.Cluster
var err error

if swag.BoolValue(params.GetUnregisteredClusters) {
if !b.authzHandler.IsAdmin(ctx) {
Expand All @@ -3072,7 +3073,11 @@ func (b *bareMetalInventory) listClustersInternal(ctx context.Context, params in
db = db.Unscoped()
}

db = b.authzHandler.OwnedByUser(ctx, db, swag.StringValue(params.Owner))
db, err = b.authzHandler.OwnedByUser(ctx, db, auth.ClusterResource, swag.StringValue(params.Owner))
if err != nil {
log.WithError(err).Error("Failed to list clusters in db")
return nil, common.NewApiError(http.StatusInternalServerError, err)
}

if params.OpenshiftClusterID != nil {
db = db.Where("openshift_cluster_id = ?", *params.OpenshiftClusterID)
Expand All @@ -3082,7 +3087,7 @@ func (b *bareMetalInventory) listClustersInternal(ctx context.Context, params in
db = db.Where("ams_subscription_id IN (?)", params.AmsSubscriptionIds)
}

dbClusters, err := common.GetClustersFromDBWhere(db, common.UseEagerLoading,
dbClusters, err = common.GetClustersFromDBWhere(db, common.UseEagerLoading,
common.DeleteRecordsState(swag.BoolValue(params.GetUnregisteredClusters)))
if err != nil {
log.WithError(err).Error("Failed to list clusters in db")
Expand Down Expand Up @@ -4458,14 +4463,19 @@ func (b *bareMetalInventory) ListInfraEnvsInternal(ctx context.Context, clusterI
db := b.db
var dbInfraEnvs []*common.InfraEnv
var infraEnvs []*models.InfraEnv
var err error

db = b.authzHandler.OwnedByUser(ctx, db, swag.StringValue(owner))
db, err = b.authzHandler.OwnedByUser(ctx, db, auth.InfraEnvResource, swag.StringValue(owner))
if err != nil {
log.WithError(err).Error("Failed to list infraEnvs in db")
return nil, err
}

if clusterId != nil {
db = db.Where("cluster_id = ?", clusterId)
}

dbInfraEnvs, err := common.GetInfraEnvsFromDBWhere(db)
dbInfraEnvs, err = common.GetInfraEnvsFromDBWhere(db)
if err != nil {
log.WithError(err).Error("Failed to list infraEnvs in db")
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion internal/events/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ func (e Events) queryEvents(ctx context.Context, params *common.V2GetEventsParam

// add authorization check to query
if e.authz != nil {
tx = e.authz.OwnedBy(ctx, tx)
tx, _ = e.authz.OwnedBy(ctx, tx, auth.EventsResource)
}

tx = e.prepareEventsTable(ctx, tx, params.ClusterID, params.HostIds, params.InfraEnvID, params.Severities, params.Message, params.DeletedHosts)
Expand Down
4 changes: 2 additions & 2 deletions internal/events/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var _ = Describe("Add event", func() {
ctrl = gomock.NewController(GinkgoT())
log := logrus.WithField("pkg", "events")
theEvents = New(db, nil, commontesting.GetDummyNotificationStream(ctrl), log)
cfg := &auth.Config{AuthType: auth.TypeRHSSO, EnableOrgTenancy: true}
cfg := &auth.Config{AuthType: auth.TypeRHSSO, EnableOrgTenancy: true, EnableOcmAuthz: false}
authz_handler := auth.NewAuthzHandler(cfg, nil, logrus.New(), db)
theEvents.(*Events).authz = authz_handler
api = &Api{handler: theEvents, log: log}
Expand Down Expand Up @@ -424,7 +424,7 @@ var _ = Describe("Events library", func() {

JustBeforeEach(func() {
//inject RHSSO authorizer to the event handler
cfg := &auth.Config{AuthType: auth.TypeRHSSO, EnableOrgTenancy: true}
cfg := &auth.Config{AuthType: auth.TypeRHSSO, EnableOrgTenancy: true, EnableOcmAuthz: false}
authz_handler := auth.NewAuthzHandler(cfg, nil, logrus.New(), db)
theEvents.(*Events).authz = authz_handler
})
Expand Down
5 changes: 5 additions & 0 deletions openshift/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ parameters:
- name: ENABLE_ORG_TENANCY
value: "false"
required: false
- name: ENABLE_OCM_AUTHZ
value: "false"
required: false
- name: ENABLE_ORG_BASED_FEATURE_GATES
value: "false"
required: false
Expand Down Expand Up @@ -471,6 +474,8 @@ objects:
value: ${CNV_SNO_INSTALL_HPP}
- name: ENABLE_ORG_TENANCY
value: ${ENABLE_ORG_TENANCY}
- name: ENABLE_OCM_AUTHZ
value: ${ENABLE_OCM_AUTHZ}
- name: ENABLE_ORG_BASED_FEATURE_GATES
value: ${ENABLE_ORG_BASED_FEATURE_GATES}
- name: ISO_IMAGE_TYPE
Expand Down
4 changes: 4 additions & 0 deletions pkg/auth/agent_local_authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ func (a *AgentLocalAuthenticator) EnableOrgTenancy() bool {
return false
}

func (a *AgentLocalAuthenticator) EnableOcmAuthz() bool {
return false
}

func (a *AgentLocalAuthenticator) EnableOrgBasedFeatureGates() bool {
return false
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/auth/auth_handler_test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,6 @@ func GenJSJWKS(privKey crypto.PublicKey, pubKey crypto.PublicKey) ([]byte, []byt

func GetConfigRHSSO() *Config {
_, cert := GetTokenAndCert(false)
cfg := &Config{JwkCert: string(cert), AuthType: TypeRHSSO, EnableOrgTenancy: true, EnableOrgBasedFeatureGates: false}
cfg := &Config{JwkCert: string(cert), AuthType: TypeRHSSO, EnableOrgTenancy: true, EnableOcmAuthz: false, EnableOrgBasedFeatureGates: false}
return cfg
}
2 changes: 2 additions & 0 deletions pkg/auth/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Authenticator interface {
AuthImageAuth(token string) (interface{}, error)
AuthType() AuthType
EnableOrgTenancy() bool
EnableOcmAuthz() bool
EnableOrgBasedFeatureGates() bool
}

Expand All @@ -40,6 +41,7 @@ type Config struct {
AllowedDomains string `envconfig:"ALLOWED_DOMAINS" default:""`
AdminUsers []string `envconfig:"ADMIN_USERS" default:""`
EnableOrgTenancy bool `envconfig:"ENABLE_ORG_TENANCY" default:"false"`
EnableOcmAuthz bool `envconfig:"ENABLE_OCM_AUTHZ" default:"false"`
EnableOrgBasedFeatureGates bool `envconfig:"ENABLE_ORG_BASED_FEATURE_GATES" default:"false"`
}

Expand Down
9 changes: 7 additions & 2 deletions pkg/auth/authz.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,29 @@ import (
)

type Action string
type Resource string

const ReadAction Action = "read"
const UpdateAction Action = "update"
const DeleteAction Action = "delete"
const NoneAction Action = "none"

const ClusterResource = "cluster"
const InfraEnvResource = "infra-env"
const EventsResource = "events"

type Authorizer interface {
/* Limits the database query to access records that are owned by the current user,
* according to the configured access policy.
*/

OwnedBy(ctx context.Context, db *gorm.DB) *gorm.DB
OwnedBy(ctx context.Context, db *gorm.DB, resource Resource) (*gorm.DB, error)

/* Limits the database query to access records owned only by the input user,
* regardless of the configured access policy. If user-based authentication
* is not supported, the function effectively will not limit access.
*/
OwnedByUser(ctx context.Context, db *gorm.DB, username string) *gorm.DB
OwnedByUser(ctx context.Context, db *gorm.DB, resource Resource, username string) (*gorm.DB, error)

/* verify that the current user has access rights (depending on the requested)
* action) to the input resource
Expand Down
4 changes: 4 additions & 0 deletions pkg/auth/local_authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ func (a *LocalAuthenticator) EnableOrgTenancy() bool {
return false
}

func (a *LocalAuthenticator) EnableOcmAuthz() bool {
return false
}

func (a *LocalAuthenticator) EnableOrgBasedFeatureGates() bool {
return false
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/auth/none_authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ func (a *NoneAuthenticator) EnableOrgTenancy() bool {
return false
}

func (a *NoneAuthenticator) EnableOcmAuthz() bool {
return false
}

func (a *NoneAuthenticator) EnableOrgBasedFeatureGates() bool {
return false
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/auth/none_authz_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ func (*NoneHandler) CreateAuthorizer() func(*http.Request) error {
}
}

func (*NoneHandler) OwnedBy(ctx context.Context, db *gorm.DB) *gorm.DB {
return db
func (*NoneHandler) OwnedBy(ctx context.Context, db *gorm.DB, resource Resource) (*gorm.DB, error) {
return db, nil
}

func (*NoneHandler) OwnedByUser(ctx context.Context, db *gorm.DB, username string) *gorm.DB {
return db
func (*NoneHandler) OwnedByUser(ctx context.Context, db *gorm.DB, resource Resource, username string) (*gorm.DB, error) {
return db, nil
}

func (*NoneHandler) HasAccessTo(ctx context.Context, obj interface{}, action Action) (bool, error) {
Expand Down
6 changes: 6 additions & 0 deletions pkg/auth/rhsso_authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type RHSSOAuthenticator struct {
KeyMap map[string]*rsa.PublicKey
AdminUsers []string
OrgTenancyEnabled bool
OcmAuthzEnabled bool
OrgBasedFunctionalityEnabled bool
utils AUtilsInteface
log logrus.FieldLogger
Expand All @@ -37,6 +38,7 @@ func NewRHSSOAuthenticator(cfg *Config, ocmCLient *ocm.Client, log logrus.FieldL
a := &RHSSOAuthenticator{
AdminUsers: cfg.AdminUsers,
OrgTenancyEnabled: cfg.EnableOrgTenancy,
OcmAuthzEnabled: cfg.EnableOcmAuthz,
OrgBasedFunctionalityEnabled: cfg.EnableOrgBasedFeatureGates,
utils: NewAuthUtils(cfg.JwkCert, cfg.JwkCertURL),
client: ocmCLient,
Expand All @@ -60,6 +62,10 @@ func (a *RHSSOAuthenticator) EnableOrgTenancy() bool {
return a.OrgTenancyEnabled
}

func (a *RHSSOAuthenticator) EnableOcmAuthz() bool {
return a.OcmAuthzEnabled
}

func (a *RHSSOAuthenticator) EnableOrgBasedFeatureGates() bool {
return a.OrgBasedFunctionalityEnabled
}
Expand Down
36 changes: 29 additions & 7 deletions pkg/auth/rhsso_authz_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ func (a *AuthzHandler) isTenancyEnabled() bool {
return a.cfg.EnableOrgTenancy
}

func (a *AuthzHandler) isOcmAuthzEnabled() bool {
return a.cfg.EnableOcmAuthz
}

func (a *AuthzHandler) isOrgBasedFunctionalityEnabled() bool {
return a.cfg.EnableOrgBasedFeatureGates
}
Expand Down Expand Up @@ -67,27 +71,40 @@ func handleOwnershipQueryError(err error) (bool, error) {
return true, nil
}

func (a *AuthzHandler) OwnedBy(ctx context.Context, db *gorm.DB) *gorm.DB {
func (a *AuthzHandler) OwnedBy(ctx context.Context, db *gorm.DB, resource Resource) (*gorm.DB, error) {
if a.IsAdmin(ctx) {
return db
return db, nil
}
if a.isOcmAuthzEnabled() {
accessibleClusterIDs, err := a.listAccessibleResource(ocm.UserNameFromContext(ctx), ocm.AMSActionGet, ClusterResource)
if err != nil {
return nil, err
}
switch resource {
case ClusterResource:
return db.Where("id in ?", accessibleClusterIDs), nil
default: // events and infra-envs
return db.Where("cluster_id in ?", accessibleClusterIDs), nil
}
}
if a.isTenancyEnabled() {
return db.Where("org_id = ?", ocm.OrgIDFromContext(ctx))
return db.Where("org_id = ?", ocm.OrgIDFromContext(ctx)), nil
} else {
return db.Where("user_name = ?", ocm.UserNameFromContext(ctx))
return db.Where("user_name = ?", ocm.UserNameFromContext(ctx)), nil
}
}

func (a *AuthzHandler) OwnedByUser(ctx context.Context, db *gorm.DB, username string) *gorm.DB {
func (a *AuthzHandler) OwnedByUser(ctx context.Context, db *gorm.DB, resource Resource, username string) (*gorm.DB, error) {
// When tenancy-based access is supported, the following query returns records
// for the input user alone. With a user-based access policy, the query returns
// the user's records, provided it is the current user. Otherwise, it returns an
// empty set since we do not support listing objects on behalf of other users in
// that mode.
if username == "" {
return a.OwnedBy(ctx, db)
return a.OwnedBy(ctx, db, resource)
}
return a.OwnedBy(ctx, db).Where("user_name = ?", username)
res, err := a.OwnedBy(ctx, db, resource)
return res.Where("user_name = ?", username), err
}

func (a *AuthzHandler) isObjectOwnedByUser(id string, obj interface{}, payload *ocm.AuthPayload) (bool, error) {
Expand Down Expand Up @@ -379,6 +396,11 @@ func (a *AuthzHandler) allowedToUseAssistedInstaller(username string) (bool, err
context.Background(), username, ocm.AMSActionCreate, "", ocm.BareMetalClusterResource)
}

func (a *AuthzHandler) listAccessibleResource(username, action, resource string) ([]string, error) {
return a.client.Authorization.ResourceReview(
context.Background(), username, action, resource)
}

func (a *AuthzHandler) hasClusterEditRole(payload *ocm.AuthPayload, action, subscriptionID string) (bool, error) {
return a.client.Authorization.AccessReview(
context.Background(), payload.Username, action, subscriptionID, ocm.Subscription)
Expand Down
6 changes: 3 additions & 3 deletions pkg/auth/rhsso_authz_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ var _ = Describe("OwnedBy", func() {
Context("tenancy disabled", func() {

BeforeEach(func() {
cfg := &Config{AuthType: TypeRHSSO, EnableOrgTenancy: false}
cfg := &Config{AuthType: TypeRHSSO, EnableOrgTenancy: false, EnableOcmAuthz: false}
handler = NewAuthzHandler(cfg, nil, logrus.New(), db)
})

Expand Down Expand Up @@ -224,7 +224,7 @@ var _ = Describe("OwnedBy", func() {
})
Context("tenancy enabled", func() {
BeforeEach(func() {
cfg := &Config{AuthType: TypeRHSSO, EnableOrgTenancy: true}
cfg := &Config{AuthType: TypeRHSSO, EnableOrgTenancy: true, EnableOcmAuthz: false}
handler = NewAuthzHandler(cfg, nil, logrus.New(), db)
})
It("admin user - empty query", func() {
Expand Down Expand Up @@ -345,7 +345,7 @@ var _ = Describe("HasAccessTo", func() {
BeforeEach(func() {
ctx = context.TODO()
ctrl = gomock.NewController(GinkgoT())
cfg := &Config{AuthType: TypeRHSSO, EnableOrgTenancy: true}
cfg := &Config{AuthType: TypeRHSSO, EnableOrgTenancy: true, EnableOcmAuthz: false}
mockOcmAuthorization = ocm.NewMockOCMAuthorization(ctrl)
ocmClient := &ocm.Client{
Authentication: ocm.NewMockOCMAuthentication(ctrl),
Expand Down
Loading

0 comments on commit 28eb660

Please sign in to comment.