зеркало из https://github.com/Azure/ARO-RP.git
use checkaccess SDK for go
This commit is contained in:
Родитель
79d1254c0d
Коммит
593c6498bb
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network"
|
||||
"github.com/Azure/checkaccess-v2-go-sdk/client"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/apparentlymart/go-cidr/cidr"
|
||||
|
@ -24,7 +25,6 @@ import (
|
|||
apisubnet "github.com/Azure/ARO-RP/pkg/api/util/subnet"
|
||||
"github.com/Azure/ARO-RP/pkg/env"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/azuresdk/armauthorization"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/compute"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/network"
|
||||
|
@ -98,7 +98,7 @@ type dynamic struct {
|
|||
resourceSkusClient compute.ResourceSkusClient
|
||||
spNetworkUsage network.UsageClient
|
||||
loadBalancerBackendAddressPoolsClient network.LoadBalancerBackendAddressPoolsClient
|
||||
pdpClient remotepdp.RemotePDPClient
|
||||
pdpClient client.RemotePDPClient
|
||||
}
|
||||
|
||||
type AuthorizerType string
|
||||
|
@ -118,7 +118,7 @@ func NewValidator(
|
|||
appID *string,
|
||||
authorizerType AuthorizerType,
|
||||
cred azcore.TokenCredential,
|
||||
pdpClient remotepdp.RemotePDPClient,
|
||||
pdpClient client.RemotePDPClient,
|
||||
) Dynamic {
|
||||
return &dynamic{
|
||||
log: log,
|
||||
|
@ -435,41 +435,61 @@ func (dv *dynamic) validateActionsByOID(ctx context.Context, r *azure.Resource,
|
|||
defer cancel()
|
||||
|
||||
c := closure{dv: dv, ctx: ctx, resource: r, actions: actions, oid: oid}
|
||||
if err := c.checkAccessAuthReqPayloadData(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return wait.PollImmediateUntil(30*time.Second, c.usingCheckAccessV2, timeoutCtx.Done())
|
||||
}
|
||||
|
||||
// closure is the closure used in PollImmediateUntil's ConditionalFunc
|
||||
type closure struct {
|
||||
dv *dynamic
|
||||
ctx context.Context
|
||||
resource *azure.Resource
|
||||
actions []string
|
||||
oid *string
|
||||
dv *dynamic
|
||||
ctx context.Context
|
||||
resource *azure.Resource
|
||||
actions []string
|
||||
oid *string
|
||||
subjectAttributes client.SubjectAttributes
|
||||
}
|
||||
|
||||
func (c *closure) checkAccessAuthReqPayloadData() error {
|
||||
c.dv.log.Info("Prepare payload for CheckAccessV2 AuthZ")
|
||||
scope := c.dv.azEnv.ResourceManagerEndpoint + "/.default"
|
||||
t, err := c.dv.checkAccessSubjectInfoCred.GetToken(c.ctx, policy.TokenRequestOptions{Scopes: []string{scope}})
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unable to get the token from AAD: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
tokenClaims, err := token.ExtractClaims(t.Token)
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unable to parse the token oid claim: ", err)
|
||||
return err
|
||||
}
|
||||
c.subjectAttributes.ObjectId = tokenClaims.ObjectId
|
||||
|
||||
if tokenClaims.ClaimNames != nil && len(tokenClaims.Groups) == 0 {
|
||||
c.subjectAttributes.ClaimName = client.GroupExpansion
|
||||
} else if tokenClaims.ClaimNames == nil && len(tokenClaims.Groups) > 0 {
|
||||
c.subjectAttributes.Groups = tokenClaims.Groups
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// usingCheckAccessV2 uses the new RBAC checkAccessV2 API
|
||||
func (c closure) usingCheckAccessV2() (bool, error) {
|
||||
c.dv.log.Info("validateActions with CheckAccessV2")
|
||||
|
||||
// reusing oid during retries
|
||||
if c.oid == nil {
|
||||
scope := c.dv.azEnv.ResourceManagerEndpoint + "/.default"
|
||||
t, err := c.dv.checkAccessSubjectInfoCred.GetToken(c.ctx, policy.TokenRequestOptions{Scopes: []string{scope}})
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unable to get the token from AAD: ", err)
|
||||
// reusing oid and groups/claimNames during retries
|
||||
if c.subjectAttributes.ObjectId == "" ||
|
||||
(c.subjectAttributes.ClaimName == "" && len(c.subjectAttributes.Groups) == 0) {
|
||||
if err := c.checkAccessAuthReqPayloadData(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
oid, err := token.GetObjectId(t.Token)
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unable to parse the token oid claim: ", err)
|
||||
return false, err
|
||||
}
|
||||
c.oid = &oid
|
||||
}
|
||||
|
||||
authReq := createAuthorizationRequest(*c.oid, c.resource.String(), c.actions...)
|
||||
authReq := c.dv.pdpClient.CreateAuthorizationRequest(c.resource.String(), c.actions, c.subjectAttributes)
|
||||
results, err := c.dv.pdpClient.CheckAccess(c.ctx, authReq)
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unexpected error when calling CheckAccessV2: ", err)
|
||||
|
@ -489,39 +509,19 @@ func (c closure) usingCheckAccessV2() (bool, error) {
|
|||
_, ok := actionsToFind[result.ActionId]
|
||||
if ok {
|
||||
delete(actionsToFind, result.ActionId)
|
||||
if result.AccessDecision != remotepdp.Allowed {
|
||||
if result.AccessDecision != client.Allowed {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(actionsToFind) > 0 {
|
||||
c.dv.log.Infof("The result didn't include permissions %v for object ID: %s", actionsToFind, *c.oid)
|
||||
c.dv.log.Infof("The result didn't include permissions %v for object ID: %s", actionsToFind, c.subjectAttributes.ObjectId)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func createAuthorizationRequest(subject, resourceId string, actions ...string) remotepdp.AuthorizationRequest {
|
||||
actionInfos := []remotepdp.ActionInfo{}
|
||||
for _, action := range actions {
|
||||
actionInfos = append(actionInfos, remotepdp.ActionInfo{Id: action})
|
||||
}
|
||||
|
||||
return remotepdp.AuthorizationRequest{
|
||||
Subject: remotepdp.SubjectInfo{
|
||||
Attributes: remotepdp.SubjectAttributes{
|
||||
ObjectId: subject,
|
||||
ClaimName: remotepdp.GroupExpansion, // always do group expansion
|
||||
},
|
||||
},
|
||||
Actions: actionInfos,
|
||||
Resource: remotepdp.ResourceInfo{
|
||||
Id: resourceId,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (dv *dynamic) validateCIDRRanges(ctx context.Context, subnets []Subnet, additionalCIDRs ...string) error {
|
||||
dv.log.Print("ValidateCIDRRanges")
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/checkaccess-v2-go-sdk/client"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"github.com/form3tech-oss/jwt-go"
|
||||
|
@ -18,7 +19,7 @@ import (
|
|||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/env"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/azuresdk/armauthorization"
|
||||
"github.com/Azure/ARO-RP/pkg/util/platformworkloadidentity"
|
||||
"github.com/Azure/ARO-RP/pkg/validate/dynamic"
|
||||
|
@ -127,11 +128,20 @@ func (dv *openShiftClusterDynamicValidator) Dynamic(ctx context.Context) error {
|
|||
}
|
||||
|
||||
aroEnv := dv.env.Environment()
|
||||
pdpClient := remotepdp.NewRemotePDPClient(
|
||||
clientOptions := &azcore.ClientOptions{
|
||||
Transport: &http.Client{
|
||||
Transport: azureclient.NewCustomRoundTripper(http.DefaultTransport),
|
||||
},
|
||||
}
|
||||
pdpClient, err := client.NewRemotePDPClient(
|
||||
fmt.Sprintf(aroEnv.Endpoint, dv.env.Location()),
|
||||
aroEnv.OAuthScope,
|
||||
fpClientCred,
|
||||
clientOptions,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scopes := []string{dv.env.Environment().ResourceManagerScope}
|
||||
var spDynamic dynamic.Dynamic
|
||||
|
|
Загрузка…
Ссылка в новой задаче