Merge branch 'master' into f/guardrails-3.15.1

This commit is contained in:
Jeff Yuan 2024-05-07 17:55:29 +12:00
Родитель 5a3b817666 227d896239
Коммит fc564970f7
121 изменённых файлов: 12605 добавлений и 2300 удалений

6
.github/workflows/ci-go.yml поставляемый
Просмотреть файл

@ -15,7 +15,7 @@ jobs:
ci-from-docker:
runs-on: ubuntu-latest
container:
image: registry.access.redhat.com/ubi8/go-toolset:1.20.10
image: registry.access.redhat.com/ubi8/go-toolset:1.20.12-5
steps:
- name: Checkout repository
uses: actions/checkout@v4
@ -32,7 +32,7 @@ jobs:
vendor-check:
runs-on: ubuntu-latest
container:
image: registry.access.redhat.com/ubi8/go-toolset:1.20.10
image: registry.access.redhat.com/ubi8/go-toolset:1.20.12-5
steps:
- name: Checkout repository
uses: actions/checkout@v4
@ -44,7 +44,7 @@ jobs:
generate-check:
runs-on: ubuntu-latest
container:
image: registry.access.redhat.com/ubi8/go-toolset:1.20.10
image: registry.access.redhat.com/ubi8/go-toolset:1.20.12-5
steps:
- name: Checkout repository
uses: actions/checkout@v4

Просмотреть файл

@ -22,7 +22,7 @@ pr:
resources:
containers:
- container: golang
image: registry.access.redhat.com/ubi8/go-toolset:1.20.10
image: registry.access.redhat.com/ubi8/go-toolset:1.20.12-5
options: --user=0
- container: python
image: registry.access.redhat.com/ubi8/python-39:latest

Просмотреть файл

@ -14,7 +14,7 @@ pr: none
variables:
Cdp_Definition_Build_Count: $[counter('', 0)] # needed for onebranch.pipeline.version task https://aka.ms/obpipelines/versioning
ONEBRANCH_AME_ACR_LOGIN: cdpxb8e9ef87cd634085ab141c637806568c00.azurecr.io
LinuxContainerImage: $(ONEBRANCH_AME_ACR_LOGIN)/b8e9ef87-cd63-4085-ab14-1c637806568c/official/ubi8/go-toolset:1.20.10 # Docker image which is used to build the project https://aka.ms/obpipelines/containers
LinuxContainerImage: $(ONEBRANCH_AME_ACR_LOGIN)/b8e9ef87-cd63-4085-ab14-1c637806568c/official/ubi8/go-toolset:1.20.12-5 # Docker image which is used to build the project https://aka.ms/obpipelines/containers
Debian_Frontend: noninteractive
resources:

Просмотреть файл

@ -14,7 +14,7 @@ pr: none
variables:
Cdp_Definition_Build_Count: $[counter('', 0)] # needed for onebranch.pipeline.version task https://aka.ms/obpipelines/versioning
ONEBRANCH_AME_ACR_LOGIN: cdpxb8e9ef87cd634085ab141c637806568c00.azurecr.io
LinuxContainerImage: $(ONEBRANCH_AME_ACR_LOGIN)/b8e9ef87-cd63-4085-ab14-1c637806568c/official/ubi8/go-toolset:1.20.10 # Docker image which is used to build the project https://aka.ms/obpipelines/containers
LinuxContainerImage: $(ONEBRANCH_AME_ACR_LOGIN)/b8e9ef87-cd63-4085-ab14-1c637806568c/official/ubi8/go-toolset:1.20.12-5 # Docker image which is used to build the project https://aka.ms/obpipelines/containers
Debian_Frontend: noninteractive
resources:

Просмотреть файл

@ -1,7 +1,7 @@
# Uses a multi-stage container build to build the RP & E2E components.
#
ARG REGISTRY
FROM ${REGISTRY}/ubi8/go-toolset:1.20.10 AS builder
FROM ${REGISTRY}/ubi8/go-toolset:1.20.12-5 AS builder
USER root
ENV GOPATH=/root/go

Просмотреть файл

@ -1,7 +1,7 @@
# Uses a multi-stage container build to build the RP.
#
ARG REGISTRY
FROM ${REGISTRY}/ubi8/go-toolset:1.20.10 AS builder
FROM ${REGISTRY}/ubi8/go-toolset:1.20.12-5 AS builder
USER root
ENV GOPATH=/root/go

Просмотреть файл

@ -1,5 +1,5 @@
ARG REGISTRY
FROM ${REGISTRY}/ubi8/go-toolset:1.20.10-1 AS builder
FROM ${REGISTRY}/ubi8/go-toolset:1.20.12-5 AS builder
ARG GATEKEEPER_VERSION
ENV DOWNLOAD_URL=https://github.com/open-policy-agent/gatekeeper/archive/${GATEKEEPER_VERSION}.tar.gz

Просмотреть файл

@ -1,7 +1,7 @@
# Uses a multi-stage container build to build the proxy
#
ARG REGISTRY
FROM ${REGISTRY}/ubi8/go-toolset:1.20.10 AS builder
FROM ${REGISTRY}/ubi8/go-toolset:1.20.12-5 AS builder
USER root
ENV GOPATH=/root/go
RUN mkdir -p /app

Просмотреть файл

@ -9,7 +9,7 @@ NO_CACHE ?= true
export GOFLAGS=$(GO_FLAGS)
# fluentbit version must also be updated in RP code, see pkg/util/version/const.go
MARINER_VERSION = 20230321
MARINER_VERSION = 20240301
FLUENTBIT_VERSION = 1.9.10
FLUENTBIT_IMAGE ?= ${RP_IMAGE_ACR}.azurecr.io/fluentbit:$(FLUENTBIT_VERSION)-cm$(MARINER_VERSION)
AUTOREST_VERSION = 3.6.3
@ -114,7 +114,8 @@ generate-kiota:
go run ./hack/licenses -dirs ./pkg/util/graph/graphsdk
init-contrib:
cp -R hack/git/hooks/* .git/hooks/
install -v hack/git/hooks/* .git/hooks/
image-aro-multistage:
docker build --platform=linux/amd64 --network=host --no-cache -f Dockerfile.aro-multistage -t $(ARO_IMAGE) --build-arg REGISTRY=$(REGISTRY) .

Просмотреть файл

@ -9,24 +9,10 @@
1. Build the development `az aro` extension:
```bash
. ./env
make az
```
1. Verify that the ARO extension path is in your `az` configuration:
```bash
grep -q 'dev_sources' ~/.azure/config || cat >>~/.azure/config <<EOF
[extension]
dev_sources = $PWD/python
EOF
```
> Alternatively, if you do not want to configure the Azure CLI to utilize
> this extension globally, you can set the `AZURE_EXTENSION_DEV_SOURCES`
> environment variable to the `./python/` subfolder of this repository, e.g.
> in your ./env environment file, when you want to use the extension, and
> unset it when you do not.
1. Verify the ARO extension is registered:
```bash
@ -41,7 +27,10 @@
```
Note: you will be able to update your development `az aro` extension in the
future by simply running `git pull`.
future by simply running `git pull`. If you need to use the "prod" extension,
what is bundled in `az` natively rather than your `./python`, you can
`unset AZURE_EXTENSION_DEV_SOURCES` (found in your `./env` file).
## Prepare your environment

Просмотреть файл

@ -267,7 +267,7 @@
--nsg-name rp-nsg \
--access Allow \
--priority 500 \
--source-address-prefixes "$(curl --silent ipecho.net/plain)/32" \
--source-address-prefixes "$(curl --silent -4 ipecho.net/plain)/32" \
--protocol Tcp \
--destination-port-ranges 22
```
@ -290,7 +290,7 @@
--nsg-name gateway-nsg \
--access Allow \
--priority 500 \
--source-address-prefixes "$(curl --silent ipecho.net/plain)/32" \
--source-address-prefixes "$(curl --silent -4 ipecho.net/plain)/32" \
--protocol Tcp \
--destination-port-ranges 22
```
@ -315,7 +315,7 @@
--nsg-name rp-nsg \
--access Allow \
--priority 499 \
--source-address-prefixes "$(curl --silent ipecho.net/plain)/32" \
--source-address-prefixes "$(curl --silent -4 ipecho.net/plain)/32" \
--protocol Tcp \
--destination-port-ranges 443
```

Просмотреть файл

@ -20,10 +20,6 @@ Subscription feature flags used by ARO-RP include:
graduating features to production such that they only apply on our Red Hat
engineering subscription.
* Microsoft.RedHatOpenShift/SaveAROTestConfig: used on our test subscriptions to
cause the pkg/billing to copy billing data to a storage account so that it can
be validated by the billing E2E tests.
Subscription feature flags are also used for API preview, INT and region
rollout. See the RP ARM manifest for more details.

Просмотреть файл

@ -139,8 +139,10 @@ Make sure that `PKG_CONFIG_PATH` contains the pkgconfig files of the above packa
cd ${GOPATH:-$HOME/go}/src/github.com/Azure/ARO-RP
```
1. Add standard git hooks
1. Configure local git
```bash
make init-contrib
git config --global github.user <<user_name>>
```

Просмотреть файл

@ -5,5 +5,6 @@ export RESOURCEGROUP=$USER-aro-$LOCATION
export DATABASE_ACCOUNT_NAME=$USER-aro-$LOCATION
export DATABASE_NAME=ARO
export KEYVAULT_PREFIX=$USER-aro-$LOCATION
export KEYVAULT_PREFIX=${KEYVAULT_PREFIX::20}
export ARO_IMAGE=${USER}aro.azurecr.io/aro:$(git rev-parse --short=7 HEAD)$([[ $(git status --porcelain) = "" ]] || echo -dirty)
export FLUENTBIT_IMAGE=${USER}aro.azurecr.io/fluentbit:latest
export FLUENTBIT_IMAGE=${USER}aro.azurecr.io/fluentbit:latest

Просмотреть файл

@ -1,5 +1,6 @@
export LOCATION=eastus
export ARO_IMAGE=arointsvc.azurecr.io/aro:latest
export NO_CACHE=false
export AZURE_EXTENSION_DEV_SOURCES="$(pwd)/python"
. secrets/env

3
go.mod
Просмотреть файл

@ -5,8 +5,9 @@ go 1.20
require (
github.com/Azure/azure-sdk-for-go v63.1.0+incompatible
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v2 v2.5.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.4.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2 v2.2.1
github.com/Azure/go-autorest/autorest v0.11.29
github.com/Azure/go-autorest/autorest/adal v0.9.23

7
go.sum
Просмотреть файл

@ -5,13 +5,16 @@ github.com/Azure/azure-sdk-for-go v63.1.0+incompatible h1:yNC7qlSUWVF8p0TzxdmWW1
github.com/Azure/azure-sdk-for-go v63.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1 h1:LNHhpdK7hzUcx/k1LIcuh5k7k1LGIWLQfCjaneSj7Fc=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.1/go.mod h1:uE9zaUfEQT/nbQjVi2IblCG9iaLtZsuYZ8ne+PuQ02M=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v2 v2.5.0 h1:FTNvxTFH/08JBmhcbL5lmLaGYVXokZM6Ni92Mqr+gSg=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v2 v2.5.0/go.mod h1:T0ryqIz5h5qg4HOBni+VeRn24alSqOx1Se1IAwUByOk=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.4.0 h1:HlZMUZW8S4P9oob1nCHxCCKrytxyLc+24nUJGssoEto=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.4.0/go.mod h1:StGsLbuJh06Bd8IBfnAlIFV3fLb+gkczONWf15hpX2E=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2 v2.2.1 h1:bWh0Z2rOEDfB/ywv/l0iHN1JgyazE6kW/aIA89+CEK0=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2 v2.2.1/go.mod h1:Bzf34hhAE9NSxailk8xVeLEZbUjOXcC+GnU1mMKdhLw=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU=

Просмотреть файл

@ -0,0 +1,46 @@
package admin
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
// PlatformWorkloadIdentityRoleSetList represents a List of role sets.
type PlatformWorkloadIdentityRoleSetList struct {
// The list of role sets.
PlatformWorkloadIdentityRoleSets []*PlatformWorkloadIdentityRoleSet `json:"value"`
}
// PlatformWorkloadIdentityRoleSet represents a mapping from the names of OCP operators to the built-in roles that should be assigned to those operator's corresponding managed identities for a particular OCP version.
type PlatformWorkloadIdentityRoleSet struct {
// The ID for the resource.
ID string `json:"id,omitempty" mutable:"case"`
// Name of the resource.
Name string `json:"name,omitempty" mutable:"case"`
// The properties for the PlatformWorkloadIdentityRoleSet resource.
Properties PlatformWorkloadIdentityRoleSetProperties `json:"properties,omitempty"`
}
// PlatformWorkloadIdentityRoleSetProperties represents the properties of a PlatformWorkloadIdentityRoleSet resource.
type PlatformWorkloadIdentityRoleSetProperties struct {
// OpenShiftVersion represents the version associated with this set of roles.
OpenShiftVersion string `json:"openShiftVersion,omitempty"`
// PlatformWorkloadIdentityRoles represents the set of roles associated with this version.
PlatformWorkloadIdentityRoles []PlatformWorkloadIdentityRole `json:"platformWorkloadIdentityRoles,omitempty" mutable:"true"`
}
// PlatformWorkloadIdentityRole represents a mapping from a particular OCP operator to the built-in role that should be assigned to that operator's corresponding managed identity.
type PlatformWorkloadIdentityRole struct {
// OperatorName represents the name of the operator that this role is for.
OperatorName string `json:"operatorName,omitempty" mutable:"true"`
// RoleDefinitionName represents the name of the role.
RoleDefinitionName string `json:"roleDefinitionName,omitempty" mutable:"true"`
// RoleDefinitionID represents the resource ID of the role definition.
RoleDefinitionID string `json:"roleDefinitionId,omitempty" mutable:"true"`
// ServiceAccounts represents the set of service accounts associated with the given operator, since each service account needs its own federated credential.
ServiceAccounts []string `json:"serviceAccounts,omitempty" mutable:"true"`
}

Просмотреть файл

@ -0,0 +1,67 @@
package admin
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
/*
TODO: Uncomment once API endpoints have been implemented and this code is being used.
type platformWorkloadIdentityRoleSetConverter struct{}
// platformWorkloadIdentityRoleSetConverter.ToExternal returns a new external representation
// of the internal object, reading from the subset of the internal object's
// fields that appear in the external representation. ToExternal does not
// modify its argument; there is no pointer aliasing between the passed and
// returned objects.
func (c platformWorkloadIdentityRoleSetConverter) ToExternal(s *api.PlatformWorkloadIdentityRoleSet) interface{} {
out := &PlatformWorkloadIdentityRoleSet{
Properties: PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: s.Properties.OpenShiftVersion,
PlatformWorkloadIdentityRoles: make([]PlatformWorkloadIdentityRole, 0, len(s.Properties.PlatformWorkloadIdentityRoles)),
},
}
for i, r := range s.Properties.PlatformWorkloadIdentityRoles {
out.Properties.PlatformWorkloadIdentityRoles[i].OperatorName = r.OperatorName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionName = r.RoleDefinitionName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionID = r.RoleDefinitionID
out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts = make([]string, 0, len(r.ServiceAccounts))
out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts = append(out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts, r.ServiceAccounts...)
}
return out
}
// ToExternalList returns a slice of external representations of the internal
// objects
func (c platformWorkloadIdentityRoleSetConverter) ToExternalList(sets []*api.PlatformWorkloadIdentityRoleSet) interface{} {
l := &PlatformWorkloadIdentityRoleSetList{
PlatformWorkloadIdentityRoleSets: make([]*PlatformWorkloadIdentityRoleSet, 0, len(sets)),
}
for _, set := range sets {
l.PlatformWorkloadIdentityRoleSets = append(l.PlatformWorkloadIdentityRoleSets, c.ToExternal(set).(*PlatformWorkloadIdentityRoleSet))
}
return l
}
// ToInternal overwrites in place a pre-existing internal object, setting (only)
// all mapped fields from the external representation. ToInternal modifies its
// argument; there is no pointer aliasing between the passed and returned
// objects
func (c platformWorkloadIdentityRoleSetConverter) ToInternal(_new interface{}, out *api.PlatformWorkloadIdentityRoleSet) {
new := _new.(*PlatformWorkloadIdentityRoleSet)
out.Properties.OpenShiftVersion = new.Properties.OpenShiftVersion
out.Properties.PlatformWorkloadIdentityRoles = make([]api.PlatformWorkloadIdentityRole, 0, len(new.Properties.PlatformWorkloadIdentityRoles))
for i, r := range new.Properties.PlatformWorkloadIdentityRoles {
out.Properties.PlatformWorkloadIdentityRoles[i].OperatorName = r.OperatorName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionName = r.RoleDefinitionName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionID = r.RoleDefinitionID
out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts = make([]string, 0, len(r.ServiceAccounts))
out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts = append(out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts, r.ServiceAccounts...)
}
}
*/

Просмотреть файл

@ -0,0 +1,71 @@
package admin
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
/*
TODO: Uncomment once API endpoints have been implemented and this code is being used.
type platformWorkloadIdentityRoleSetStaticValidator struct{}
func (sv platformWorkloadIdentityRoleSetStaticValidator) Static(_new interface{}, _current *api.PlatformWorkloadIdentityRoleSet) error {
new := _new.(*PlatformWorkloadIdentityRoleSet)
var current *PlatformWorkloadIdentityRoleSet
if _current != nil {
current = (&platformWorkloadIdentityRoleSetConverter{}).ToExternal(_current).(*PlatformWorkloadIdentityRoleSet)
}
err := sv.validate(new, current == nil)
if err != nil {
return err
}
if current == nil {
return nil
}
return sv.validateDelta(new, current)
}
func (sv platformWorkloadIdentityRoleSetStaticValidator) validate(new *PlatformWorkloadIdentityRoleSet, isCreate bool) error {
if new.Properties.OpenShiftVersion == "" {
return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, "properties.openShiftVersion", "Must be provided")
}
if new.Properties.PlatformWorkloadIdentityRoles == nil || len(new.Properties.PlatformWorkloadIdentityRoles) == 0 {
return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, "properties.platformWorkloadIdentityRoles", "Must be provided and must be non-empty")
}
errs := []error{}
for i, r := range new.Properties.PlatformWorkloadIdentityRoles {
if r.OperatorName == "" {
errs = append(errs, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].operatorName", i), "Must be provided"))
}
if r.RoleDefinitionName == "" {
errs = append(errs, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].roleDefinitionName", i), "Must be provided"))
}
if r.RoleDefinitionID == "" {
errs = append(errs, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].roleDefinitionId", i), "Must be provided"))
}
if r.ServiceAccounts == nil || len(r.ServiceAccounts) == 0 {
errs = append(errs, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].serviceAccounts", i), "Must be provided and must be non-empty"))
}
}
return errors.Join(errs...)
}
func (sv platformWorkloadIdentityRoleSetStaticValidator) validateDelta(new, current *PlatformWorkloadIdentityRoleSet) error {
err := immutable.Validate("", new, current)
if err != nil {
err := err.(*immutable.ValidationError)
return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodePropertyChangeNotAllowed, err.Target, err.Message)
}
return nil
}
*/

Просмотреть файл

@ -4,11 +4,6 @@ package api
// Licensed under the Apache License 2.0.
const (
// FeatureFlagSaveAROTestConfig is the feature in the subscription that is used
// to indicate if we need to save ARO cluster config into the E2E
// StorageAccount
FeatureFlagSaveAROTestConfig = "Microsoft.RedHatOpenShift/SaveAROTestConfig"
// FeatureFlagMTU3900 is the feature in the subscription that causes new
// OpenShift cluster nodes to use the largest available Maximum Transmission
// Unit (MTU) on Azure virtual networks, which as of late 2021 is 3900 bytes.

Просмотреть файл

@ -0,0 +1,30 @@
package api
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
// PlatformWorkloadIdentityRoleSet represents a mapping from the names of OCP operators to the built-in roles that should be assigned to those operator's corresponding managed identities for a particular OCP version.
type PlatformWorkloadIdentityRoleSet struct {
MissingFields
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Deleting bool `json:"deleting,omitempty"` // https://docs.microsoft.com/en-us/azure/cosmos-db/change-feed-design-patterns#deletes
Properties PlatformWorkloadIdentityRoleSetProperties `json:"properties,omitempty"`
}
// PlatformWorkloadIdentityRoleSetProperties represents the properties of a PlatformWorkloadIdentityRoleSet resource.
type PlatformWorkloadIdentityRoleSetProperties struct {
OpenShiftVersion string `json:"openShiftVersion,omitempty"`
PlatformWorkloadIdentityRoles []PlatformWorkloadIdentityRole `json:"platformWorkloadIdentityRoles,omitempty"`
}
// PlatformWorkloadIdentityRole represents a mapping from a particular OCP operator to the built-in role that should be assigned to that operator's corresponding managed identity.
type PlatformWorkloadIdentityRole struct {
OperatorName string `json:"operatorName,omitempty"`
RoleDefinitionName string `json:"roleDefinitionName,omitempty"`
RoleDefinitionID string `json:"roleDefinitionId,omitempty"`
ServiceAccounts []string `json:"serviceAccounts,omitempty"`
}

Просмотреть файл

@ -0,0 +1,38 @@
package api
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
// PlatformWorkloadIdentityRoleSetDocuments represents a set of PlatformWorkloadIdentityRoleSetDocuments.
// pkg/database/cosmosdb requires its definition.
type PlatformWorkloadIdentityRoleSetDocuments struct {
Count int `json:"_count,omitempty"`
ResourceID string `json:"_rid,omitempty"`
PlatformWorkloadIdentityRoleSetDocuments []*PlatformWorkloadIdentityRoleSetDocument `json:"Documents,omitempty"`
}
func (c *PlatformWorkloadIdentityRoleSetDocuments) String() string {
return encodeJSON(c)
}
// PlatformWorkloadIdentityRoleSetDocument represents a document specifying a mapping from the names of OCP operators to the built-in roles that should be assigned to those operator's corresponding managed identities for a particular OCP version.
// pkg/database/cosmosdb requires its definition.
type PlatformWorkloadIdentityRoleSetDocument struct {
MissingFields
ID string `json:"id,omitempty"`
ResourceID string `json:"_rid,omitempty"`
Timestamp int `json:"_ts,omitempty"`
Self string `json:"_self,omitempty"`
ETag string `json:"_etag,omitempty" deep:"-"`
Attachments string `json:"_attachments,omitempty"`
TTL int `json:"ttl,omitempty"`
LSN int `json:"_lsn,omitempty"`
Metadata map[string]interface{} `json:"_metadata,omitempty"`
PlatformWorkloadIdentityRoleSet *PlatformWorkloadIdentityRoleSet `json:"platformWorkloadIdentityRoleSet,omitempty"`
}
func (c *PlatformWorkloadIdentityRoleSetDocument) String() string {
return encodeJSON(c)
}

Просмотреть файл

@ -0,0 +1,29 @@
package api
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
func ExamplePlatformWorkloadIdentityRoleSetDocument() *PlatformWorkloadIdentityRoleSetDocument {
return &PlatformWorkloadIdentityRoleSetDocument{
MissingFields: MissingFields{},
ID: "00000000-0000-0000-0000-000000000000",
PlatformWorkloadIdentityRoleSet: &PlatformWorkloadIdentityRoleSet{
ID: "00000000-0000-0000-0000-000000000000",
Name: "4.14",
Type: "Microsoft.RedHatOpenShift/PlatformWorkloadIdentityRoleSet",
Properties: PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []PlatformWorkloadIdentityRole{
{
OperatorName: "ServiceOperator",
RoleDefinitionName: "AzureRedHatOpenShiftServiceOperator",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/00000000-0000-0000-0000-000000000000",
ServiceAccounts: []string{
"aro-operator-master",
},
},
},
},
},
}
}

Просмотреть файл

@ -15,13 +15,7 @@ import (
var secretPreservingJSONHandle *codec.JsonHandle
func init() {
secretPreservingJSONHandle = &codec.JsonHandle{
BasicHandle: codec.BasicHandle{
DecodeOptions: codec.DecodeOptions{
ErrorIfNoField: true,
},
},
}
secretPreservingJSONHandle = &codec.JsonHandle{}
err := secretPreservingJSONHandle.SetInterfaceExt(reflect.TypeOf(SecureBytes{}), 1, secureHidingExt{})
if err != nil {

Просмотреть файл

@ -277,4 +277,11 @@ func (c openShiftClusterConverter) ExternalNoReadOnly(_oc interface{}) {
if oc.Properties.NetworkProfile.LoadBalancerProfile != nil {
oc.Properties.NetworkProfile.LoadBalancerProfile.EffectiveOutboundIPs = nil
}
oc.SystemData = nil
oc.Properties.ConsoleProfile.URL = ""
oc.Properties.APIServerProfile.URL = ""
oc.Properties.APIServerProfile.IP = ""
for i := range oc.Properties.IngressProfiles {
oc.Properties.IngressProfiles[i].IP = ""
}
}

Просмотреть файл

@ -326,4 +326,15 @@ func (c openShiftClusterConverter) ExternalNoReadOnly(_oc interface{}) {
if oc.Properties.NetworkProfile.LoadBalancerProfile != nil {
oc.Properties.NetworkProfile.LoadBalancerProfile.EffectiveOutboundIPs = nil
}
oc.SystemData = nil
oc.Properties.ConsoleProfile.URL = ""
oc.Properties.APIServerProfile.URL = ""
oc.Properties.APIServerProfile.IP = ""
for i := range oc.Properties.IngressProfiles {
oc.Properties.IngressProfiles[i].IP = ""
}
for i := range oc.Properties.PlatformWorkloadIdentityProfile.PlatformWorkloadIdentities {
oc.Properties.PlatformWorkloadIdentityProfile.PlatformWorkloadIdentities[i].ClientID = ""
oc.Properties.PlatformWorkloadIdentityProfile.PlatformWorkloadIdentities[i].ObjectID = ""
}
}

Просмотреть файл

@ -0,0 +1,51 @@
package v20240812preview
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
// PlatformWorkloadIdentityRoleSetList represents a List of role sets.
type PlatformWorkloadIdentityRoleSetList struct {
// The list of role sets.
PlatformWorkloadIdentityRoleSets []*PlatformWorkloadIdentityRoleSet `json:"value"`
// Next Link to next operation.
NextLink string `json:"nextLink,omitempty"`
}
// PlatformWorkloadIdentityRoleSet represents a mapping from the names of OCP operators to the built-in roles that should be assigned to those operator's corresponding managed identities for a particular OCP version.
type PlatformWorkloadIdentityRoleSet struct {
proxyResource bool
// The ID for the resource.
ID string `json:"id,omitempty" mutable:"case"`
// Name of the resource.
Name string `json:"name,omitempty" mutable:"case"`
// The resource type.
Type string `json:"type,omitempty" mutable:"case"`
// The properties for the PlatformWorkloadIdentityRoleSet resource.
Properties PlatformWorkloadIdentityRoleSetProperties `json:"properties,omitempty"`
}
// PlatformWorkloadIdentityRoleSetProperties represents the properties of a PlatformWorkloadIdentityRoleSet resource.
type PlatformWorkloadIdentityRoleSetProperties struct {
// OpenShiftVersion represents the version associated with this set of roles.
OpenShiftVersion string `json:"openShiftVersion,omitempty"`
// PlatformWorkloadIdentityRoles represents the set of roles associated with this version.
PlatformWorkloadIdentityRoles []PlatformWorkloadIdentityRole `json:"platformWorkloadIdentityRoles,omitempty"`
}
// PlatformWorkloadIdentityRole represents a mapping from a particular OCP operator to the built-in role that should be assigned to that operator's corresponding managed identity.
type PlatformWorkloadIdentityRole struct {
// OperatorName represents the name of the operator that this role is for.
OperatorName string `json:"operatorName,omitempty"`
// RoleDefinitionName represents the name of the role.
RoleDefinitionName string `json:"roleDefinitionName,omitempty"`
// RoleDefinitionID represents the resource ID of the role definition.
RoleDefinitionID string `json:"roleDefinitionId,omitempty"`
}

Просмотреть файл

@ -0,0 +1,65 @@
package v20240812preview
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"github.com/Azure/ARO-RP/pkg/api"
)
type platformWorkloadIdentityRoleSetConverter struct{}
// platformWorkloadIdentityRoleSetConverter.ToExternal returns a new external representation
// of the internal object, reading from the subset of the internal object's
// fields that appear in the external representation. ToExternal does not
// modify its argument; there is no pointer aliasing between the passed and
// returned objects.
func (c platformWorkloadIdentityRoleSetConverter) ToExternal(s *api.PlatformWorkloadIdentityRoleSet) interface{} {
out := &PlatformWorkloadIdentityRoleSet{
ID: s.ID,
proxyResource: true,
Properties: PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: s.Properties.OpenShiftVersion,
PlatformWorkloadIdentityRoles: make([]PlatformWorkloadIdentityRole, 0, len(s.Properties.PlatformWorkloadIdentityRoles)),
},
}
for i, r := range s.Properties.PlatformWorkloadIdentityRoles {
out.Properties.PlatformWorkloadIdentityRoles[i].OperatorName = r.OperatorName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionName = r.RoleDefinitionName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionID = r.RoleDefinitionID
}
return out
}
// ToExternalList returns a slice of external representations of the internal
// objects
func (c platformWorkloadIdentityRoleSetConverter) ToExternalList(sets []*api.PlatformWorkloadIdentityRoleSet) interface{} {
l := &PlatformWorkloadIdentityRoleSetList{
PlatformWorkloadIdentityRoleSets: make([]*PlatformWorkloadIdentityRoleSet, 0, len(sets)),
}
for _, set := range sets {
l.PlatformWorkloadIdentityRoleSets = append(l.PlatformWorkloadIdentityRoleSets, c.ToExternal(set).(*PlatformWorkloadIdentityRoleSet))
}
return l
}
// ToInternal overwrites in place a pre-existing internal object, setting (only)
// all mapped fields from the external representation. ToInternal modifies its
// argument; there is no pointer aliasing between the passed and returned
// objects
func (c platformWorkloadIdentityRoleSetConverter) ToInternal(_new interface{}, out *api.PlatformWorkloadIdentityRoleSet) {
new := _new.(*PlatformWorkloadIdentityRoleSet)
out.Properties.OpenShiftVersion = new.Properties.OpenShiftVersion
out.Properties.PlatformWorkloadIdentityRoles = make([]api.PlatformWorkloadIdentityRole, 0, len(new.Properties.PlatformWorkloadIdentityRoles))
for i, r := range new.Properties.PlatformWorkloadIdentityRoles {
out.Properties.PlatformWorkloadIdentityRoles[i].OperatorName = r.OperatorName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionName = r.RoleDefinitionName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionID = r.RoleDefinitionID
}
}

Просмотреть файл

@ -0,0 +1,24 @@
package v20240812preview
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import "github.com/Azure/ARO-RP/pkg/api"
func examplePlatformWorkloadIdentityRoleSet() *PlatformWorkloadIdentityRoleSet {
doc := api.ExamplePlatformWorkloadIdentityRoleSetDocument()
ext := (&platformWorkloadIdentityRoleSetConverter{}).ToExternal(doc.PlatformWorkloadIdentityRoleSet)
return ext.(*PlatformWorkloadIdentityRoleSet)
}
func ExamplePlatformWorkloadIdentityRoleSetResponse() interface{} {
return examplePlatformWorkloadIdentityRoleSet()
}
func ExamplePlatformWorkloadIdentityRoleSetListResponse() interface{} {
return &PlatformWorkloadIdentityRoleSetList{
PlatformWorkloadIdentityRoleSets: []*PlatformWorkloadIdentityRoleSet{
ExamplePlatformWorkloadIdentityRoleSetResponse().(*PlatformWorkloadIdentityRoleSet),
},
}
}

Просмотреть файл

@ -27,7 +27,7 @@ import (
testlog "github.com/Azure/ARO-RP/test/util/log"
)
const TEST_PULLSPEC = "registry.access.redhat.com/ubi8/go-toolset:1.20.10"
const TEST_PULLSPEC = "registry.access.redhat.com/ubi8/go-toolset:1.20.12-5"
var _ = Describe("Podman", Ordered, func() {
var err error

Просмотреть файл

@ -78,13 +78,7 @@ func getDatabaseKey(keys sdkcosmos.DatabaseAccountsClientListKeysResponse, log *
}
func NewJSONHandle(aead encryption.AEAD) (*codec.JsonHandle, error) {
h := &codec.JsonHandle{
BasicHandle: codec.BasicHandle{
DecodeOptions: codec.DecodeOptions{
ErrorIfNoField: true,
},
},
}
h := &codec.JsonHandle{}
if aead == nil {
return h, nil

Просмотреть файл

@ -11,160 +11,167 @@
},
"resources": [
{
"apiVersion": "2023-04-15",
"location": "[resourceGroup().location]",
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'))]",
"properties": {
"resource": {
"id": "[parameters('databaseName')]"
},
"options": {
"autoscaleSettings": {
"maxThroughput": 1000
}
},
"resource": {
"id": "[parameters('databaseName')]"
}
},
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'))]",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
"location": "[resourceGroup().location]",
"apiVersion": "2021-01-15"
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases"
},
{
"apiVersion": "2023-04-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
],
"location": "[resourceGroup().location]",
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/AsyncOperations')]",
"properties": {
"options": {},
"resource": {
"defaultTtl": 604800,
"id": "AsyncOperations",
"partitionKey": {
"kind": "Hash",
"paths": [
"/id"
],
"kind": "Hash"
},
"defaultTtl": 604800
},
"options": {}
]
}
}
},
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/AsyncOperations')]",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
"location": "[resourceGroup().location]",
"apiVersion": "2021-01-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
]
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
},
{
"apiVersion": "2023-04-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
],
"location": "[resourceGroup().location]",
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/OpenShiftVersions')]",
"properties": {
"options": {},
"resource": {
"defaultTtl": -1,
"id": "OpenShiftVersions",
"partitionKey": {
"kind": "Hash",
"paths": [
"/id"
],
"kind": "Hash"
},
"defaultTtl": -1
},
"options": {}
]
}
}
},
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/OpenShiftVersions')]",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
"location": "[resourceGroup().location]",
"apiVersion": "2021-01-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
]
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
},
{
"apiVersion": "2023-04-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
],
"location": "[resourceGroup().location]",
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/ClusterManagerConfigurations')]",
"properties": {
"options": {},
"resource": {
"id": "ClusterManagerConfigurations",
"partitionKey": {
"kind": "Hash",
"paths": [
"/partitionKey"
],
"kind": "Hash"
]
}
},
"options": {}
}
},
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/ClusterManagerConfigurations')]",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
"location": "[resourceGroup().location]",
"apiVersion": "2021-01-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
]
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
},
{
"apiVersion": "2023-04-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
],
"location": "[resourceGroup().location]",
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/Billing')]",
"properties": {
"options": {},
"resource": {
"id": "Billing",
"partitionKey": {
"kind": "Hash",
"paths": [
"/id"
],
"kind": "Hash"
]
}
},
"options": {}
}
},
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/Billing')]",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
"location": "[resourceGroup().location]",
"apiVersion": "2021-01-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
]
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
},
{
"apiVersion": "2023-04-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
],
"location": "[resourceGroup().location]",
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/Gateway')]",
"properties": {
"options": {},
"resource": {
"defaultTtl": -1,
"id": "Gateway",
"partitionKey": {
"kind": "Hash",
"paths": [
"/id"
],
"kind": "Hash"
},
"defaultTtl": -1
},
"options": {}
]
}
}
},
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/Gateway')]",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
"location": "[resourceGroup().location]",
"apiVersion": "2021-01-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
]
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
},
{
"apiVersion": "2023-04-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
],
"location": "[resourceGroup().location]",
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/Monitors')]",
"properties": {
"options": {},
"resource": {
"defaultTtl": -1,
"id": "Monitors",
"partitionKey": {
"kind": "Hash",
"paths": [
"/id"
],
"kind": "Hash"
},
"defaultTtl": -1
},
"options": {}
]
}
}
},
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/Monitors')]",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
"location": "[resourceGroup().location]",
"apiVersion": "2021-01-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
]
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
},
{
"apiVersion": "2023-04-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
],
"location": "[resourceGroup().location]",
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/OpenShiftClusters')]",
"properties": {
"options": {},
"resource": {
"id": "OpenShiftClusters",
"partitionKey": {
"kind": "Hash",
"paths": [
"/partitionKey"
],
"kind": "Hash"
]
},
"uniqueKeyPolicy": {
"uniqueKeys": [
@ -185,59 +192,52 @@
}
]
}
},
"options": {}
}
},
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/OpenShiftClusters')]",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
"location": "[resourceGroup().location]",
"apiVersion": "2021-01-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
]
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
},
{
"apiVersion": "2023-04-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
],
"location": "[resourceGroup().location]",
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/Portal')]",
"properties": {
"options": {},
"resource": {
"defaultTtl": -1,
"id": "Portal",
"partitionKey": {
"kind": "Hash",
"paths": [
"/id"
],
"kind": "Hash"
},
"defaultTtl": -1
},
"options": {}
]
}
}
},
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/Portal')]",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
"location": "[resourceGroup().location]",
"apiVersion": "2021-01-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
]
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
},
{
"apiVersion": "2023-04-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
],
"location": "[resourceGroup().location]",
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/Subscriptions')]",
"properties": {
"options": {},
"resource": {
"id": "Subscriptions",
"partitionKey": {
"kind": "Hash",
"paths": [
"/id"
],
"kind": "Hash"
]
}
},
"options": {}
}
},
"name": "[concat(parameters('databaseAccountName'), '/', parameters('databaseName'), '/Subscriptions')]",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
"location": "[resourceGroup().location]",
"apiVersion": "2021-01-15",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('databaseName'))]"
]
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
}
]
}

Просмотреть файл

@ -224,7 +224,7 @@
},
"properties": {
"upgradePolicy": {
"mode": "Manual"
"mode": "Rolling"
},
"virtualMachineProfile": {
"osProfile": {
@ -296,7 +296,7 @@
"autoUpgradeMinorVersion": true,
"settings": {},
"protectedSettings": {
"script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('I0FkZGluZyByZXRyeSBsb2dpYyB0byB5dW0gY29tbWFuZHMgaW4gb3JkZXIgdG8gYXZvaWQgc3RhbGxpbmcgb3V0IG9uIHJlc291cmNlIGxvY2tzCmVjaG8gInJ1bm5pbmcgUkhVSSBmaXgiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gdXBkYXRlIC15IC0tZGlzYWJsZXJlcG89JyonIC0tZW5hYmxlcmVwbz0ncmh1aS1taWNyb3NvZnQtYXp1cmUqJyAmJiBicmVhawogIGlmIFtbICR7YXR0ZW1wdH0gLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgplY2hvICJydW5uaW5nIHl1bSB1cGRhdGUiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gLXkgLXggV0FMaW51eEFnZW50IC14IFdBTGludXhBZ2VudC11ZGV2IHVwZGF0ZSAtLWFsbG93ZXJhc2luZyAmJiBicmVhawogIGlmIFtbICR7YXR0ZW1wdH0gLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgplY2hvICJpbnN0YWxsaW5nIHBvZG1hbi1kb2NrZXIiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gLXkgaW5zdGFsbCBwb2RtYW4tZG9ja2VyICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmZpcmV3YWxsLWNtZCAtLWFkZC1wb3J0PTQ0My90Y3AgLS1wZXJtYW5lbnQKCm1rZGlyIC9yb290Ly5kb2NrZXIKY2F0ID4vcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIDw8RU9GCnsKCSJhdXRocyI6IHsKCQkiJHtQUk9YWUlNQUdFJSUvKn0iOiB7CgkJCSJhdXRoIjogIiRQUk9YWUlNQUdFQVVUSCIKCQl9Cgl9Cn0KRU9GCgpta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCnRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKZG9ja2VyIHB1bGwgIiRQUk9YWUlNQUdFIgoKbWtkaXIgL2V0Yy9wcm94eQpiYXNlNjQgLWQgPDw8IiRQUk9YWUNFUlQiID4vZXRjL3Byb3h5L3Byb3h5LmNydApiYXNlNjQgLWQgPDw8IiRQUk9YWUtFWSIgPi9ldGMvcHJveHkvcHJveHkua2V5CmJhc2U2NCAtZCA8PDwiJFBST1hZQ0xJRU5UQ0VSVCIgPi9ldGMvcHJveHkvcHJveHktY2xpZW50LmNydApjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9wcm94eQpjaG1vZCAwNjAwIC9ldGMvcHJveHkvcHJveHkua2V5CgpjYXQgPi9ldGMvc3lzY29uZmlnL3Byb3h5IDw8RU9GClBST1hZX0lNQUdFPSckUFJPWFlJTUFHRScKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vcHJveHkuc2VydmljZSA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL3Byb3h5CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVuCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIC0tcm0gLS1uYW1lICVuIC1wIDQ0Mzo4NDQzIC12IC9ldGMvcHJveHk6L3NlY3JldHMgJFBST1hZX0lNQUdFCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wICVuClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CkVPRgoKc3lzdGVtY3RsIGVuYWJsZSBwcm94eS5zZXJ2aWNlCgpjYXQgPi9ldGMvY3Jvbi53ZWVrbHkvcHVsbC1pbWFnZSA8PCdFT0YnCiMhL2Jpbi9iYXNoCgpkb2NrZXIgcHVsbCAkUFJPWFlJTUFHRQpzeXN0ZW1jdGwgcmVzdGFydCBwcm94eS5zZXJ2aWNlCkVPRgpjaG1vZCAreCAvZXRjL2Nyb24ud2Vla2x5L3B1bGwtaW1hZ2UKCmNhdCA+L2V0Yy9jcm9uLndlZWtseS95dW11cGRhdGUgPDwnRU9GJwojIS9iaW4vYmFzaAoKeXVtIHVwZGF0ZSAteQpFT0YKY2htb2QgK3ggL2V0Yy9jcm9uLndlZWtseS95dW11cGRhdGUKCmNhdCA+L2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHkgPDwnRU9GJwojIS9iaW4vYmFzaAoKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZQpFT0YKY2htb2QgK3ggL2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHkKCigKCXNsZWVwIDMwCglyZWJvb3QKKSAmCg==')))]"
"script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('I0FkZGluZyByZXRyeSBsb2dpYyB0byB5dW0gY29tbWFuZHMgaW4gb3JkZXIgdG8gYXZvaWQgc3RhbGxpbmcgb3V0IG9uIHJlc291cmNlIGxvY2tzCmVjaG8gInJ1bm5pbmcgUkhVSSBmaXgiCmZvciBhdHRlbXB0IGluIHsxLi42MH07IGRvCiAgeXVtIHVwZGF0ZSAteSAtLWRpc2FibGVyZXBvPScqJyAtLWVuYWJsZXJlcG89J3JodWktbWljcm9zb2Z0LWF6dXJlKicgJiYgYnJlYWsKICBpZiBbWyAke2F0dGVtcHR9IC1sdCA2MCBdXTsgdGhlbiBzbGVlcCAzMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gInJ1bm5pbmcgeXVtIHVwZGF0ZSIKZm9yIGF0dGVtcHQgaW4gezEuLjYwfTsgZG8KICB5dW0gLXkgLXggV0FMaW51eEFnZW50IC14IFdBTGludXhBZ2VudC11ZGV2IHVwZGF0ZSAtLWFsbG93ZXJhc2luZyAmJiBicmVhawogIGlmIFtbICR7YXR0ZW1wdH0gLWx0IDYwIF1dOyB0aGVuIHNsZWVwIDMwOyBlbHNlIGV4aXQgMTsgZmkKZG9uZQoKZWNobyAiaW5zdGFsbGluZyBwb2RtYW4tZG9ja2VyIgpmb3IgYXR0ZW1wdCBpbiB7MS4uNjB9OyBkbwogIHl1bSAteSBpbnN0YWxsIHBvZG1hbi1kb2NrZXIgJiYgYnJlYWsKICBpZiBbWyAke2F0dGVtcHR9IC1sdCA2MCBdXTsgdGhlbiBzbGVlcCAzMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmZpcmV3YWxsLWNtZCAtLWFkZC1wb3J0PTQ0My90Y3AgLS1wZXJtYW5lbnQKCm1rZGlyIC9yb290Ly5kb2NrZXIKY2F0ID4vcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIDw8RU9GCnsKCSJhdXRocyI6IHsKCQkiJHtQUk9YWUlNQUdFJSUvKn0iOiB7CgkJCSJhdXRoIjogIiRQUk9YWUlNQUdFQVVUSCIKCQl9Cgl9Cn0KRU9GCgpta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCnRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKZG9ja2VyIHB1bGwgIiRQUk9YWUlNQUdFIgoKbWtkaXIgL2V0Yy9wcm94eQpiYXNlNjQgLWQgPDw8IiRQUk9YWUNFUlQiID4vZXRjL3Byb3h5L3Byb3h5LmNydApiYXNlNjQgLWQgPDw8IiRQUk9YWUtFWSIgPi9ldGMvcHJveHkvcHJveHkua2V5CmJhc2U2NCAtZCA8PDwiJFBST1hZQ0xJRU5UQ0VSVCIgPi9ldGMvcHJveHkvcHJveHktY2xpZW50LmNydApjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9wcm94eQpjaG1vZCAwNjAwIC9ldGMvcHJveHkvcHJveHkua2V5CgpjYXQgPi9ldGMvc3lzY29uZmlnL3Byb3h5IDw8RU9GClBST1hZX0lNQUdFPSckUFJPWFlJTUFHRScKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vcHJveHkuc2VydmljZSA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL3Byb3h5CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVuCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIC0tcm0gLS1uYW1lICVuIC1wIDQ0Mzo4NDQzIC12IC9ldGMvcHJveHk6L3NlY3JldHMgJFBST1hZX0lNQUdFCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wICVuClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CkVPRgoKc3lzdGVtY3RsIGVuYWJsZSBwcm94eS5zZXJ2aWNlCgpjYXQgPi9ldGMvY3Jvbi53ZWVrbHkvcHVsbC1pbWFnZSA8PCdFT0YnCiMhL2Jpbi9iYXNoCgpkb2NrZXIgcHVsbCAkUFJPWFlJTUFHRQpzeXN0ZW1jdGwgcmVzdGFydCBwcm94eS5zZXJ2aWNlCkVPRgpjaG1vZCAreCAvZXRjL2Nyb24ud2Vla2x5L3B1bGwtaW1hZ2UKCmNhdCA+L2V0Yy9jcm9uLndlZWtseS95dW11cGRhdGUgPDwnRU9GJwojIS9iaW4vYmFzaAoKeXVtIHVwZGF0ZSAteQpFT0YKY2htb2QgK3ggL2V0Yy9jcm9uLndlZWtseS95dW11cGRhdGUKCmNhdCA+L2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHkgPDwnRU9GJwojIS9iaW4vYmFzaAoKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZQpFT0YKY2htb2QgK3ggL2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHkKCigKCXNsZWVwIDMwCglyZWJvb3QKKSAmCg==')))]"
},
"provisionAfterExtensions": [
"Microsoft.Azure.Monitor.AzureMonitorLinuxAgent",

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -26,7 +26,8 @@
{
"actions": [
"Microsoft.Resources/subscriptions/resourceGroups/read",
"Microsoft.Resources/subscriptions/resourceGroups/write"
"Microsoft.Resources/subscriptions/resourceGroups/write",
"Microsoft.Authorization/*/action"
]
}
],

Просмотреть файл

@ -54,32 +54,33 @@
"location": "[resourceGroup().location]"
},
{
"apiVersion": "2023-04-15",
"kind": "GlobalDocumentDB",
"location": "[resourceGroup().location]",
"name": "[parameters('databaseAccountName')]",
"properties": {
"consistencyPolicy": {
"defaultConsistencyLevel": "Strong"
},
"locations": [
{
"locationName": "[resourceGroup().location]"
}
],
"databaseAccountOfferType": "Standard",
"backupPolicy": {
"periodicModeProperties": {
"backupIntervalInMinutes": 240,
"backupRetentionIntervalInHours": 720
},
"type": "Periodic"
}
},
"consistencyPolicy": {
"defaultConsistencyLevel": "Strong"
},
"databaseAccountOfferType": "Standard",
"locations": [
{
"locationName": "[resourceGroup().location]"
}
],
"minimalTlsVersion": "Tls12"
},
"name": "[parameters('databaseAccountName')]",
"type": "Microsoft.DocumentDB/databaseAccounts",
"location": "[resourceGroup().location]",
"tags": {
"defaultExperience": "Core (SQL)"
},
"apiVersion": "2021-01-15"
"type": "Microsoft.DocumentDB/databaseAccounts"
},
{
"name": "[guid(resourceGroup().id, parameters('rpServicePrincipalId'), 'RP / Reader')]",

Просмотреть файл

@ -29,12 +29,6 @@
"azureSecPackVSATenantId": {
"value": ""
},
"billingE2EStorageAccountId": {
"value": ""
},
"billingServicePrincipalId": {
"value": ""
},
"clusterDefaultInstallerPullspec": {
"value": ""
},

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -48,8 +48,6 @@ type Configuration struct {
ARMAPICABundle *string `json:"armApiCaBundle,omitempty"`
ARMAPIClientCertCommonName *string `json:"armApiClientCertCommonName,omitempty"`
ARMClientID *string `json:"armClientId,omitempty"`
BillingE2EStorageAccountID *string `json:"billingE2EStorageAccountId,omitempty"`
BillingServicePrincipalID *string `json:"billingServicePrincipalId,omitempty"`
ClusterMDMAccount *string `json:"clusterMdmAccount,omitempty" value:"required"`
ClusterMDSDAccount *string `json:"clusterMdsdAccount,omitempty" value:"required"`
ClusterMDSDConfigVersion *string `json:"clusterMdsdConfigVersion,omitempty" value:"required"`

Просмотреть файл

@ -53,7 +53,7 @@ func (g *generator) devProxyVMSS() *arm.Resource {
},
VirtualMachineScaleSetProperties: &mgmtcompute.VirtualMachineScaleSetProperties{
UpgradePolicy: &mgmtcompute.UpgradePolicy{
Mode: mgmtcompute.UpgradeModeManual,
Mode: mgmtcompute.UpgradeModeRolling,
},
VirtualMachineProfile: &mgmtcompute.VirtualMachineScaleSetVMProfile{
OsProfile: &mgmtcompute.VirtualMachineScaleSetOSProfile{

Просмотреть файл

@ -259,7 +259,7 @@ func (g *generator) gatewayVMSS() *arm.Resource {
Tags: map[string]*string{},
VirtualMachineScaleSetProperties: &mgmtcompute.VirtualMachineScaleSetProperties{
UpgradePolicy: &mgmtcompute.UpgradePolicy{
Mode: mgmtcompute.UpgradeModeManual,
Mode: mgmtcompute.UpgradeModeRolling,
},
VirtualMachineProfile: &mgmtcompute.VirtualMachineScaleSetVMProfile{
OsProfile: &mgmtcompute.VirtualMachineScaleSetOSProfile{

Просмотреть файл

@ -8,8 +8,8 @@ import (
"fmt"
"strings"
sdkcosmos "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v2"
mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute"
mgmtdocumentdb "github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2021-01-15/documentdb"
mgmtkeyvault "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2019-09-01/keyvault"
mgmtmsi "github.com/Azure/azure-sdk-for-go/services/msi/mgmt/2018-11-30/msi"
mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network"
@ -457,7 +457,6 @@ func (g *generator) rpVMSS() *arm.Resource {
"azureCloudName",
"azureSecPackQualysUrl",
"azureSecPackVSATenantId",
"billingE2EStorageAccountId",
"clusterMdmAccount",
"clusterMdsdAccount",
"clusterMdsdConfigVersion",
@ -548,7 +547,7 @@ func (g *generator) rpVMSS() *arm.Resource {
Tags: map[string]*string{},
VirtualMachineScaleSetProperties: &mgmtcompute.VirtualMachineScaleSetProperties{
UpgradePolicy: &mgmtcompute.UpgradePolicy{
Mode: mgmtcompute.UpgradeModeManual,
Mode: mgmtcompute.UpgradeModeRolling,
},
VirtualMachineProfile: &mgmtcompute.VirtualMachineScaleSetVMProfile{
OsProfile: &mgmtcompute.VirtualMachineScaleSetOSProfile{
@ -978,25 +977,31 @@ func (g *generator) rpServiceKeyvault() *arm.Resource {
}
func (g *generator) rpCosmosDB() []*arm.Resource {
cosmosdb := &mgmtdocumentdb.DatabaseAccountCreateUpdateParameters{
Kind: mgmtdocumentdb.GlobalDocumentDB,
DatabaseAccountCreateUpdateProperties: &mgmtdocumentdb.DatabaseAccountCreateUpdateProperties{
ConsistencyPolicy: &mgmtdocumentdb.ConsistencyPolicy{
DefaultConsistencyLevel: mgmtdocumentdb.Strong,
dbType := sdkcosmos.DatabaseAccountKindGlobalDocumentDB
consistency := sdkcosmos.DefaultConsistencyLevelStrong
backupPolicy := sdkcosmos.BackupPolicyTypePeriodic
minTLSVersion := sdkcosmos.MinimalTLSVersionTls12
cosmosdb := &sdkcosmos.DatabaseAccountCreateUpdateParameters{
Kind: &dbType,
Properties: &sdkcosmos.DatabaseAccountCreateUpdateProperties{
ConsistencyPolicy: &sdkcosmos.ConsistencyPolicy{
DefaultConsistencyLevel: &consistency,
},
Locations: &[]mgmtdocumentdb.Location{
Locations: []*sdkcosmos.Location{
{
LocationName: to.StringPtr("[resourceGroup().location]"),
},
},
DatabaseAccountOfferType: to.StringPtr(string(mgmtdocumentdb.Standard)),
BackupPolicy: mgmtdocumentdb.PeriodicModeBackupPolicy{
Type: mgmtdocumentdb.TypePeriodic,
PeriodicModeProperties: &mgmtdocumentdb.PeriodicModeProperties{
DatabaseAccountOfferType: to.StringPtr("Standard"),
BackupPolicy: &sdkcosmos.PeriodicModeBackupPolicy{
Type: &backupPolicy,
PeriodicModeProperties: &sdkcosmos.PeriodicModeProperties{
BackupIntervalInMinutes: to.Int32Ptr(240), //4 hours
BackupRetentionIntervalInHours: to.Int32Ptr(720), //30 days
},
},
MinimalTLSVersion: &minTLSVersion,
},
Name: to.StringPtr("[parameters('databaseAccountName')]"),
Type: to.StringPtr("Microsoft.DocumentDB/databaseAccounts"),
@ -1009,12 +1014,13 @@ func (g *generator) rpCosmosDB() []*arm.Resource {
r := &arm.Resource{
Resource: cosmosdb,
APIVersion: azureclient.APIVersion("Microsoft.DocumentDB"),
Type: "Microsoft.DocumentDB/databaseAccounts",
}
if g.production {
cosmosdb.IPRules = &[]mgmtdocumentdb.IPAddressOrRange{}
cosmosdb.IsVirtualNetworkFilterEnabled = to.BoolPtr(true)
cosmosdb.VirtualNetworkRules = &[]mgmtdocumentdb.VirtualNetworkRule{}
cosmosdb.DisableKeyBasedMetadataWriteAccess = to.BoolPtr(true)
cosmosdb.Properties.IPRules = []*sdkcosmos.IPAddressOrRange{}
cosmosdb.Properties.IsVirtualNetworkFilterEnabled = to.BoolPtr(true)
cosmosdb.Properties.VirtualNetworkRules = []*sdkcosmos.VirtualNetworkRule{}
cosmosdb.Properties.DisableKeyBasedMetadataWriteAccess = to.BoolPtr(true)
}
rs := []*arm.Resource{
@ -1031,12 +1037,12 @@ func (g *generator) rpCosmosDB() []*arm.Resource {
func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Resource {
database := &arm.Resource{
Resource: &mgmtdocumentdb.SQLDatabaseCreateUpdateParameters{
SQLDatabaseCreateUpdateProperties: &mgmtdocumentdb.SQLDatabaseCreateUpdateProperties{
Resource: &mgmtdocumentdb.SQLDatabaseResource{
Resource: &sdkcosmos.SQLDatabaseCreateUpdateParameters{
Properties: &sdkcosmos.SQLDatabaseCreateUpdateProperties{
Resource: &sdkcosmos.SQLDatabaseResource{
ID: to.StringPtr("[" + databaseName + "]"),
},
Options: &mgmtdocumentdb.CreateUpdateOptions{
Options: &sdkcosmos.CreateUpdateOptions{
Throughput: to.Int32Ptr(cosmosDbStandardProvisionedThroughputHack),
},
},
@ -1045,21 +1051,23 @@ func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Reso
Location: to.StringPtr("[resourceGroup().location]"),
},
APIVersion: azureclient.APIVersion("Microsoft.DocumentDB"),
Type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
}
hashPartitionKey := sdkcosmos.PartitionKindHash
portal := &arm.Resource{
Resource: &mgmtdocumentdb.SQLContainerCreateUpdateParameters{
SQLContainerCreateUpdateProperties: &mgmtdocumentdb.SQLContainerCreateUpdateProperties{
Resource: &mgmtdocumentdb.SQLContainerResource{
Resource: &sdkcosmos.SQLContainerCreateUpdateParameters{
Properties: &sdkcosmos.SQLContainerCreateUpdateProperties{
Resource: &sdkcosmos.SQLContainerResource{
ID: to.StringPtr("Portal"),
PartitionKey: &mgmtdocumentdb.ContainerPartitionKey{
Paths: &[]string{
"/id",
PartitionKey: &sdkcosmos.ContainerPartitionKey{
Paths: []*string{
to.StringPtr("/id"),
},
Kind: mgmtdocumentdb.PartitionKindHash,
Kind: &hashPartitionKey,
},
DefaultTTL: to.Int32Ptr(-1),
},
Options: &mgmtdocumentdb.CreateUpdateOptions{
Options: &sdkcosmos.CreateUpdateOptions{
Throughput: to.Int32Ptr(cosmosDbPortalProvisionedThroughputHack),
},
},
@ -1071,22 +1079,23 @@ func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Reso
DependsOn: []string{
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), " + databaseName + ")]",
},
Type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
}
gateway := &arm.Resource{
Resource: &mgmtdocumentdb.SQLContainerCreateUpdateParameters{
SQLContainerCreateUpdateProperties: &mgmtdocumentdb.SQLContainerCreateUpdateProperties{
Resource: &mgmtdocumentdb.SQLContainerResource{
Resource: &sdkcosmos.SQLContainerCreateUpdateParameters{
Properties: &sdkcosmos.SQLContainerCreateUpdateProperties{
Resource: &sdkcosmos.SQLContainerResource{
ID: to.StringPtr("Gateway"),
PartitionKey: &mgmtdocumentdb.ContainerPartitionKey{
Paths: &[]string{
"/id",
PartitionKey: &sdkcosmos.ContainerPartitionKey{
Paths: []*string{
to.StringPtr("/id"),
},
Kind: mgmtdocumentdb.PartitionKindHash,
Kind: &hashPartitionKey,
},
DefaultTTL: to.Int32Ptr(-1),
},
Options: &mgmtdocumentdb.CreateUpdateOptions{
Options: &sdkcosmos.CreateUpdateOptions{
Throughput: to.Int32Ptr(cosmosDbGatewayProvisionedThroughputHack),
},
},
@ -1098,34 +1107,35 @@ func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Reso
DependsOn: []string{
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), " + databaseName + ")]",
},
Type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
}
if !g.production {
database.Resource.(*mgmtdocumentdb.SQLDatabaseCreateUpdateParameters).SQLDatabaseCreateUpdateProperties.Options = &mgmtdocumentdb.CreateUpdateOptions{
AutoscaleSettings: &mgmtdocumentdb.AutoscaleSettings{
database.Resource.(*sdkcosmos.SQLDatabaseCreateUpdateParameters).Properties.Options = &sdkcosmos.CreateUpdateOptions{
AutoscaleSettings: &sdkcosmos.AutoscaleSettings{
MaxThroughput: to.Int32Ptr(1000),
},
}
portal.Resource.(*mgmtdocumentdb.SQLContainerCreateUpdateParameters).SQLContainerCreateUpdateProperties.Options = &mgmtdocumentdb.CreateUpdateOptions{}
gateway.Resource.(*mgmtdocumentdb.SQLContainerCreateUpdateParameters).SQLContainerCreateUpdateProperties.Options = &mgmtdocumentdb.CreateUpdateOptions{}
portal.Resource.(*sdkcosmos.SQLContainerCreateUpdateParameters).Properties.Options = &sdkcosmos.CreateUpdateOptions{}
gateway.Resource.(*sdkcosmos.SQLContainerCreateUpdateParameters).Properties.Options = &sdkcosmos.CreateUpdateOptions{}
}
rs := []*arm.Resource{
database,
{
Resource: &mgmtdocumentdb.SQLContainerCreateUpdateParameters{
SQLContainerCreateUpdateProperties: &mgmtdocumentdb.SQLContainerCreateUpdateProperties{
Resource: &mgmtdocumentdb.SQLContainerResource{
Resource: &sdkcosmos.SQLContainerCreateUpdateParameters{
Properties: &sdkcosmos.SQLContainerCreateUpdateProperties{
Resource: &sdkcosmos.SQLContainerResource{
ID: to.StringPtr("AsyncOperations"),
PartitionKey: &mgmtdocumentdb.ContainerPartitionKey{
Paths: &[]string{
"/id",
PartitionKey: &sdkcosmos.ContainerPartitionKey{
Paths: []*string{
to.StringPtr("/id"),
},
Kind: mgmtdocumentdb.PartitionKindHash,
Kind: &hashPartitionKey,
},
DefaultTTL: to.Int32Ptr(7 * 86400), // 7 days
},
Options: &mgmtdocumentdb.CreateUpdateOptions{},
Options: &sdkcosmos.CreateUpdateOptions{},
},
Name: to.StringPtr("[concat(parameters('databaseAccountName'), '/', " + databaseName + ", '/AsyncOperations')]"),
Type: to.StringPtr("Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"),
@ -1135,21 +1145,22 @@ func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Reso
DependsOn: []string{
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), " + databaseName + ")]",
},
Type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
},
{
Resource: &mgmtdocumentdb.SQLContainerCreateUpdateParameters{
SQLContainerCreateUpdateProperties: &mgmtdocumentdb.SQLContainerCreateUpdateProperties{
Resource: &mgmtdocumentdb.SQLContainerResource{
Resource: &sdkcosmos.SQLContainerCreateUpdateParameters{
Properties: &sdkcosmos.SQLContainerCreateUpdateProperties{
Resource: &sdkcosmos.SQLContainerResource{
ID: to.StringPtr("OpenShiftVersions"),
PartitionKey: &mgmtdocumentdb.ContainerPartitionKey{
Paths: &[]string{
"/id",
PartitionKey: &sdkcosmos.ContainerPartitionKey{
Paths: []*string{
to.StringPtr("/id"),
},
Kind: mgmtdocumentdb.PartitionKindHash,
Kind: &hashPartitionKey,
},
DefaultTTL: to.Int32Ptr(-1),
},
Options: &mgmtdocumentdb.CreateUpdateOptions{},
Options: &sdkcosmos.CreateUpdateOptions{},
},
Name: to.StringPtr("[concat(parameters('databaseAccountName'), '/', " + databaseName + ", '/OpenShiftVersions')]"),
Type: to.StringPtr("Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"),
@ -1159,20 +1170,21 @@ func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Reso
DependsOn: []string{
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), " + databaseName + ")]",
},
Type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
},
{
Resource: &mgmtdocumentdb.SQLContainerCreateUpdateParameters{
SQLContainerCreateUpdateProperties: &mgmtdocumentdb.SQLContainerCreateUpdateProperties{
Resource: &mgmtdocumentdb.SQLContainerResource{
Resource: &sdkcosmos.SQLContainerCreateUpdateParameters{
Properties: &sdkcosmos.SQLContainerCreateUpdateProperties{
Resource: &sdkcosmos.SQLContainerResource{
ID: to.StringPtr("ClusterManagerConfigurations"),
PartitionKey: &mgmtdocumentdb.ContainerPartitionKey{
Paths: &[]string{
"/partitionKey",
PartitionKey: &sdkcosmos.ContainerPartitionKey{
Paths: []*string{
to.StringPtr("/partitionKey"),
},
Kind: mgmtdocumentdb.PartitionKindHash,
Kind: &hashPartitionKey,
},
},
Options: &mgmtdocumentdb.CreateUpdateOptions{},
Options: &sdkcosmos.CreateUpdateOptions{},
},
Name: to.StringPtr("[concat(parameters('databaseAccountName'), '/', " + databaseName + ", '/ClusterManagerConfigurations')]"),
Type: to.StringPtr("Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"),
@ -1182,20 +1194,21 @@ func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Reso
DependsOn: []string{
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), " + databaseName + ")]",
},
Type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
},
{
Resource: &mgmtdocumentdb.SQLContainerCreateUpdateParameters{
SQLContainerCreateUpdateProperties: &mgmtdocumentdb.SQLContainerCreateUpdateProperties{
Resource: &mgmtdocumentdb.SQLContainerResource{
Resource: &sdkcosmos.SQLContainerCreateUpdateParameters{
Properties: &sdkcosmos.SQLContainerCreateUpdateProperties{
Resource: &sdkcosmos.SQLContainerResource{
ID: to.StringPtr("Billing"),
PartitionKey: &mgmtdocumentdb.ContainerPartitionKey{
Paths: &[]string{
"/id",
PartitionKey: &sdkcosmos.ContainerPartitionKey{
Paths: []*string{
to.StringPtr("/id"),
},
Kind: mgmtdocumentdb.PartitionKindHash,
Kind: &hashPartitionKey,
},
},
Options: &mgmtdocumentdb.CreateUpdateOptions{},
Options: &sdkcosmos.CreateUpdateOptions{},
},
Name: to.StringPtr("[concat(parameters('databaseAccountName'), '/', " + databaseName + ", '/Billing')]"),
Type: to.StringPtr("Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"),
@ -1205,22 +1218,23 @@ func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Reso
DependsOn: []string{
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), " + databaseName + ")]",
},
Type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
},
gateway,
{
Resource: &mgmtdocumentdb.SQLContainerCreateUpdateParameters{
SQLContainerCreateUpdateProperties: &mgmtdocumentdb.SQLContainerCreateUpdateProperties{
Resource: &mgmtdocumentdb.SQLContainerResource{
Resource: &sdkcosmos.SQLContainerCreateUpdateParameters{
Properties: &sdkcosmos.SQLContainerCreateUpdateProperties{
Resource: &sdkcosmos.SQLContainerResource{
ID: to.StringPtr("Monitors"),
PartitionKey: &mgmtdocumentdb.ContainerPartitionKey{
Paths: &[]string{
"/id",
PartitionKey: &sdkcosmos.ContainerPartitionKey{
Paths: []*string{
to.StringPtr("/id"),
},
Kind: mgmtdocumentdb.PartitionKindHash,
Kind: &hashPartitionKey,
},
DefaultTTL: to.Int32Ptr(-1),
},
Options: &mgmtdocumentdb.CreateUpdateOptions{},
Options: &sdkcosmos.CreateUpdateOptions{},
},
Name: to.StringPtr("[concat(parameters('databaseAccountName'), '/', " + databaseName + ", '/Monitors')]"),
Type: to.StringPtr("Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"),
@ -1230,39 +1244,40 @@ func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Reso
DependsOn: []string{
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), " + databaseName + ")]",
},
Type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
},
{
Resource: &mgmtdocumentdb.SQLContainerCreateUpdateParameters{
SQLContainerCreateUpdateProperties: &mgmtdocumentdb.SQLContainerCreateUpdateProperties{
Resource: &mgmtdocumentdb.SQLContainerResource{
Resource: &sdkcosmos.SQLContainerCreateUpdateParameters{
Properties: &sdkcosmos.SQLContainerCreateUpdateProperties{
Resource: &sdkcosmos.SQLContainerResource{
ID: to.StringPtr("OpenShiftClusters"),
PartitionKey: &mgmtdocumentdb.ContainerPartitionKey{
Paths: &[]string{
"/partitionKey",
PartitionKey: &sdkcosmos.ContainerPartitionKey{
Paths: []*string{
to.StringPtr("/partitionKey"),
},
Kind: mgmtdocumentdb.PartitionKindHash,
Kind: &hashPartitionKey,
},
UniqueKeyPolicy: &mgmtdocumentdb.UniqueKeyPolicy{
UniqueKeys: &[]mgmtdocumentdb.UniqueKey{
UniqueKeyPolicy: &sdkcosmos.UniqueKeyPolicy{
UniqueKeys: []*sdkcosmos.UniqueKey{
{
Paths: &[]string{
"/key",
Paths: []*string{
to.StringPtr("/key"),
},
},
{
Paths: &[]string{
"/clusterResourceGroupIdKey",
Paths: []*string{
to.StringPtr("/clusterResourceGroupIdKey"),
},
},
{
Paths: &[]string{
"/clientIdKey",
Paths: []*string{
to.StringPtr("/clientIdKey"),
},
},
},
},
},
Options: &mgmtdocumentdb.CreateUpdateOptions{},
Options: &sdkcosmos.CreateUpdateOptions{},
},
Name: to.StringPtr("[concat(parameters('databaseAccountName'), '/', " + databaseName + ", '/OpenShiftClusters')]"),
Type: to.StringPtr("Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"),
@ -1272,21 +1287,22 @@ func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Reso
DependsOn: []string{
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), " + databaseName + ")]",
},
Type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
},
portal,
{
Resource: &mgmtdocumentdb.SQLContainerCreateUpdateParameters{
SQLContainerCreateUpdateProperties: &mgmtdocumentdb.SQLContainerCreateUpdateProperties{
Resource: &mgmtdocumentdb.SQLContainerResource{
Resource: &sdkcosmos.SQLContainerCreateUpdateParameters{
Properties: &sdkcosmos.SQLContainerCreateUpdateProperties{
Resource: &sdkcosmos.SQLContainerResource{
ID: to.StringPtr("Subscriptions"),
PartitionKey: &mgmtdocumentdb.ContainerPartitionKey{
Paths: &[]string{
"/id",
PartitionKey: &sdkcosmos.ContainerPartitionKey{
Paths: []*string{
to.StringPtr("/id"),
},
Kind: mgmtdocumentdb.PartitionKindHash,
Kind: &hashPartitionKey,
},
},
Options: &mgmtdocumentdb.CreateUpdateOptions{},
Options: &sdkcosmos.CreateUpdateOptions{},
},
Name: to.StringPtr("[concat(parameters('databaseAccountName'), '/', " + databaseName + ", '/Subscriptions')]"),
Type: to.StringPtr("Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"),
@ -1296,6 +1312,7 @@ func (g *generator) database(databaseName string, addDependsOn bool) []*arm.Reso
DependsOn: []string{
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), " + databaseName + ")]",
},
Type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
},
}
@ -1426,19 +1443,6 @@ func (g *generator) rpRBAC() []*arm.Resource {
}
}
func (g *generator) rpBillingContributorRbac() []*arm.Resource {
return []*arm.Resource{
rbac.ResourceRoleAssignmentWithName(
rbac.RoleDocumentDBAccountContributor,
"parameters('billingServicePrincipalId')",
"Microsoft.DocumentDB/databaseAccounts",
"parameters('databaseAccountName')",
"concat(parameters('databaseAccountName'), '/Microsoft.Authorization/', guid(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('databaseAccountName')), parameters('billingServicePrincipalId') , 'Billing / DocumentDB Account Contributor'))",
"[greater(length(parameters('billingServicePrincipalId')), 0)]",
),
}
}
func (g *generator) rpACR() *arm.Resource {
return &arm.Resource{
Resource: &mgmtcontainerregistry.Registry{

Просмотреть файл

@ -1,20 +1,20 @@
#Adding retry logic to yum commands in order to avoid stalling out on resource locks
echo "running RHUI fix"
for attempt in {1..5}; do
for attempt in {1..60}; do
yum update -y --disablerepo='*' --enablerepo='rhui-microsoft-azure*' && break
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
echo "running yum update"
for attempt in {1..5}; do
for attempt in {1..60}; do
yum -y -x WALinuxAgent -x WALinuxAgent-udev update --allowerasing && break
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
echo "installing podman-docker"
for attempt in {1..5}; do
for attempt in {1..60}; do
yum -y install podman-docker && break
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
firewall-cmd --add-port=443/tcp --permanent

Просмотреть файл

@ -7,15 +7,15 @@ systemctl reload sshd.service
#Adding retry logic to yum commands in order to avoid stalling out on resource locks
echo "running RHUI fix"
for attempt in {1..5}; do
for attempt in {1..60}; do
yum update -y --disablerepo='*' --enablerepo='rhui-microsoft-azure*' && break
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
echo "running yum update"
for attempt in {1..5}; do
for attempt in {1..60}; do
yum -y -x WALinuxAgent -x WALinuxAgent-udev update --allowerasing && break
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
echo "extending partition table"
@ -34,9 +34,9 @@ xfs_growfs /var
rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8
rpm --import https://packages.microsoft.com/keys/microsoft.asc
for attempt in {1..5}; do
for attempt in {1..60}; do
yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && break
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
echo "configuring logrotate"
@ -111,10 +111,10 @@ EOF
semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?"
mkdir -p /var/log/journal
for attempt in {1..5}; do
for attempt in {1..60}; do
yum -y install clamav azsec-clamav azsec-monitor azure-cli azure-mdsd azure-security podman-docker openssl-perl python3 && break
# hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
echo "applying firewall rules"

Просмотреть файл

@ -7,15 +7,15 @@ systemctl reload sshd.service
#Adding retry logic to yum commands in order to avoid stalling out on resource locks
echo "running RHUI fix"
for attempt in {1..5}; do
for attempt in {1..60}; do
yum update -y --disablerepo='*' --enablerepo='rhui-microsoft-azure*' && break
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
echo "running yum update"
for attempt in {1..5}; do
for attempt in {1..60}; do
yum -y -x WALinuxAgent -x WALinuxAgent-udev update --allowerasing && break
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
echo "extending partition table"
@ -35,9 +35,9 @@ echo "importing rpm repositories"
rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8
rpm --import https://packages.microsoft.com/keys/microsoft.asc
for attempt in {1..5}; do
for attempt in {1..60}; do
yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && break
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
echo "configuring logrotate"
@ -95,10 +95,10 @@ EOF
semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?"
mkdir -p /var/log/journal
for attempt in {1..5}; do
for attempt in {1..60}; do
yum -y install clamav azsec-clamav azsec-monitor azure-cli azure-mdsd azure-security podman podman-docker openssl-perl python3 && break
# hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505
if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi
if [[ ${attempt} -lt 60 ]]; then sleep 30; else exit 1; fi
done
# https://access.redhat.com/security/cve/cve-2020-13401
@ -272,7 +272,6 @@ ARM_API_CLIENT_CERT_COMMON_NAME='$ARMAPICLIENTCERTCOMMONNAME'
AZURE_ARM_CLIENT_ID='$ARMCLIENTID'
AZURE_FP_CLIENT_ID='$FPCLIENTID'
AZURE_FP_SERVICE_PRINCIPAL_ID='$FPSERVICEPRINCIPALID'
BILLING_E2E_STORAGE_ACCOUNT_ID='$BILLINGE2ESTORAGEACCOUNTID'
CLUSTER_MDM_ACCOUNT='$CLUSTERMDMACCOUNT'
CLUSTER_MDM_NAMESPACE=RP
CLUSTER_MDSD_ACCOUNT='$CLUSTERMDSDACCOUNT'
@ -312,7 +311,6 @@ ExecStart=/usr/bin/docker run \
-e ARM_API_CLIENT_CERT_COMMON_NAME \
-e AZURE_ARM_CLIENT_ID \
-e AZURE_FP_CLIENT_ID \
-e BILLING_E2E_STORAGE_ACCOUNT_ID \
-e CLUSTER_MDM_ACCOUNT \
-e CLUSTER_MDM_NAMESPACE \
-e CLUSTER_MDSD_ACCOUNT \

Просмотреть файл

@ -41,8 +41,6 @@ func (g *generator) rpTemplate() *arm.Template {
"azureCloudName",
"azureSecPackQualysUrl",
"azureSecPackVSATenantId",
"billingE2EStorageAccountId",
"billingServicePrincipalId",
"clusterMdmAccount",
"clusterMdsdAccount",
"clusterMdsdConfigVersion",
@ -100,8 +98,6 @@ func (g *generator) rpTemplate() *arm.Template {
case "armApiCaBundle",
"armApiClientCertCommonName",
"armClientId",
"billingServicePrincipalId",
"billingE2EStorageAccountId",
"gatewayDomains",
"rpFeatures":
p.DefaultValue = ""
@ -177,7 +173,6 @@ func (g *generator) rpTemplate() *arm.Template {
g.rpLBAlert(67.0, 3, "rp-degraded-alert", "PT15M", "PT6H", "DipAvailability"), // 1/3 backend down for 1h or 2/3 down for 3h in the last 6h
g.rpLBAlert(33.0, 2, "rp-vnet-alert", "PT5M", "PT5M", "VipAvailability")) // this will trigger only if the Azure network infrastructure between the loadBalancers and VMs is down for 3.5min
// more on alerts https://msazure.visualstudio.com/AzureRedHatOpenShift/_wiki/wikis/ARO.wiki/53765/WIP-Alerting
t.Resources = append(t.Resources, g.rpBillingContributorRbac()...)
t.Resources = append(t.Resources,
g.virtualNetworkPeering("rp-vnet/peering-gateway-vnet", "[resourceId(parameters('gatewayResourceGroupName'), 'Microsoft.Network/virtualNetworks', 'gateway-vnet')]", false, false, nil),

Просмотреть файл

@ -149,9 +149,10 @@ func (f *frontend) _putOrPatchOpenShiftCluster(ctx context.Context, log *logrus.
// Patch should be used for updating individual fields of the document.
case http.MethodPatch:
ext = converter.ToExternal(doc.OpenShiftCluster)
converter.ExternalNoReadOnly(ext)
}
converter.ExternalNoReadOnly(ext)
err = json.Unmarshal(body, &ext)
if err != nil {
return nil, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidRequestContent, "", "The request content was invalid and could not be deserialized: %q.", err)

Просмотреть файл

@ -51,11 +51,6 @@ func (f *frontend) _putSubscription(ctx context.Context, r *http.Request) ([]byt
oldState := doc.Subscription.State
h := &codec.JsonHandle{
BasicHandle: codec.BasicHandle{
DecodeOptions: codec.DecodeOptions{
ErrorIfNoField: true,
},
},
Indent: 4,
}

Просмотреть файл

@ -7,13 +7,47 @@ import (
"encoding/json"
"fmt"
"reflect"
"strings"
sdkcosmos "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v2"
gofrsuuid "github.com/gofrs/uuid"
)
// MarshalJSON marshals the nested r.Resource ignoring any MarshalJSON() methods
// on its types. It then merges remaining fields of r over the result
func (r *Resource) MarshalJSON() ([]byte, error) {
var b []byte
var err error
// hack to handle newer track2 sdk which doesn't have json tags
if strings.HasPrefix(r.Type, "Microsoft.DocumentDB/databaseAccounts/sqlDatabases") {
if reflect.TypeOf(r.Resource) == reflect.TypeOf(&sdkcosmos.SQLDatabaseCreateUpdateParameters{}) {
b, err = r.Resource.(*sdkcosmos.SQLDatabaseCreateUpdateParameters).MarshalJSON()
} else if reflect.TypeOf(r.Resource) == reflect.TypeOf(&sdkcosmos.SQLContainerCreateUpdateParameters{}) {
b, err = r.Resource.(*sdkcosmos.SQLContainerCreateUpdateParameters).MarshalJSON()
}
} else if strings.HasPrefix(r.Type, "Microsoft.DocumentDB/databaseAccounts") {
b, err = r.Resource.(*sdkcosmos.DatabaseAccountCreateUpdateParameters).MarshalJSON()
}
if err != nil {
return b, err
}
if b != nil {
dataMap := map[string]interface{}{}
err = json.Unmarshal(b, &dataMap)
if err != nil {
return nil, err
}
dataMap["apiVersion"] = r.APIVersion
if r.DependsOn != nil {
dataMap["dependsOn"] = r.DependsOn
}
return json.Marshal(dataMap)
}
resource := reflect.ValueOf(shadowCopy(r.Resource))
outer := reflect.ValueOf(*r)

Просмотреть файл

@ -19,7 +19,7 @@ var apiVersions = map[string]string{
"microsoft.compute/snapshots": "2020-05-01",
"microsoft.containerregistry": "2020-11-01-preview",
"microsoft.resources/deployments": "2021-04-01",
"microsoft.documentdb": "2021-01-15",
"microsoft.documentdb": "2023-04-15",
"microsoft.insights": "2018-03-01",
"microsoft.keyvault": "2019-09-01",
"microsoft.keyvault/vaults/accesspolicies": "2021-10-01",

Просмотреть файл

@ -0,0 +1,30 @@
package armkeyvault
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault"
"github.com/Azure/ARO-RP/pkg/util/azureclient/azuresdk/azcore"
)
type VaultsClient interface {
CheckNameAvailability(ctx context.Context, vaultName armkeyvault.VaultCheckNameAvailabilityParameters, options *armkeyvault.VaultsClientCheckNameAvailabilityOptions) (armkeyvault.VaultsClientCheckNameAvailabilityResponse, error)
}
type vaultsClient struct {
*armkeyvault.VaultsClient
}
var _ VaultsClient = &vaultsClient{}
func NewVaultsClient(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (VaultsClient, error) {
client, err := armkeyvault.NewVaultsClient(subscriptionID, credential, options)
return vaultsClient{
VaultsClient: client,
}, err
}

Просмотреть файл

@ -4,5 +4,5 @@ package authorization
// Licensed under the Apache License 2.0.
//go:generate rm -rf ../../../../util/mocks/$GOPACKAGE
//go:generate go run ../../../../../vendor/github.com/golang/mock/mockgen -destination=../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/$GOPACKAGE PermissionsClient,RoleAssignmentsClient,DenyAssignmentClient,RoleDefinitionsClient
//go:generate go run ../../../../../vendor/github.com/golang/mock/mockgen -destination=../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/$GOPACKAGE RoleAssignmentsClient,DenyAssignmentClient,RoleDefinitionsClient
//go:generate go run ../../../../../vendor/golang.org/x/tools/cmd/goimports -local=github.com/Azure/ARO-RP -e -w ../../../../util/mocks/azureclient/mgmt/$GOPACKAGE/$GOPACKAGE.go

Просмотреть файл

@ -1,32 +0,0 @@
package authorization
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
mgmtauthorization "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-09-01-preview/authorization"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/ARO-RP/pkg/util/azureclient"
)
// PermissionsClient is a minimal interface for azure PermissionsClient
type PermissionsClient interface {
PermissionsClientAddons
}
type permissionsClient struct {
mgmtauthorization.PermissionsClient
}
var _ PermissionsClient = &permissionsClient{}
// NewPermissionsClient creates a new PermissionsClient
func NewPermissionsClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) PermissionsClient {
client := mgmtauthorization.NewPermissionsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID)
client.Authorizer = authorizer
return &permissionsClient{
PermissionsClient: client,
}
}

Просмотреть файл

@ -1,60 +0,0 @@
package authorization
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"context"
mgmtauthorization "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-09-01-preview/authorization"
)
// PermissionsClientAddons contains addons for PermissionsClient
type PermissionsClientAddons interface {
ListForResource(ctx context.Context, resourceGroupName string, resourceProviderNamespace string, parentResourcePath string, resourceType string, resourceName string) (permissions []mgmtauthorization.Permission, err error)
ListForResourceGroup(ctx context.Context, resourceGroupName string) (permissions []mgmtauthorization.Permission, err error)
}
func (c *permissionsClient) ListForResource(ctx context.Context, resourceGroupName string, resourceProviderNamespace string, parentResourcePath string, resourceType string, resourceName string) (permissions []mgmtauthorization.Permission, err error) {
page, err := c.PermissionsClient.ListForResource(ctx, resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName)
if err != nil {
return nil, err
}
for {
permissions = append(permissions, page.Values()...)
err = page.NextWithContext(ctx)
if err != nil {
return nil, err
}
if !page.NotDone() {
break
}
}
return permissions, nil
}
func (c *permissionsClient) ListForResourceGroup(ctx context.Context, resourceGroupName string) (permissions []mgmtauthorization.Permission, error error) {
page, err := c.PermissionsClient.ListForResourceGroup(ctx, resourceGroupName)
if err != nil {
return nil, err
}
for {
permissions = append(permissions, page.Values()...)
err = page.NextWithContext(ctx)
if err != nil {
return nil, err
}
if !page.NotDone() {
break
}
}
return permissions, nil
}

Просмотреть файл

@ -5,6 +5,7 @@ package compute
import (
"context"
"time"
mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute"
"github.com/Azure/go-autorest/autorest"
@ -28,6 +29,7 @@ var _ VirtualMachinesClient = &virtualMachinesClient{}
func NewVirtualMachinesClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) VirtualMachinesClient {
client := mgmtcompute.NewVirtualMachinesClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID)
client.Authorizer = authorizer
client.PollingDuration = 30 * time.Minute
return &virtualMachinesClient{
VirtualMachinesClient: client,

Просмотреть файл

@ -1,34 +0,0 @@
package keyvault
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"context"
mgmtkeyvault "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2019-09-01/keyvault"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/ARO-RP/pkg/util/azureclient"
)
// VaultsClient is a minimal interface for azure VaultsClient
type VaultsClient interface {
CheckNameAvailability(ctx context.Context, vaultName mgmtkeyvault.VaultCheckNameAvailabilityParameters) (result mgmtkeyvault.CheckNameAvailabilityResult, err error)
}
type vaultsClient struct {
mgmtkeyvault.VaultsClient
}
var _ VaultsClient = &vaultsClient{}
// NewVaultsClient creates a new KeyvaultClient
func NewVaultsClient(environment *azureclient.AROEnvironment, subscriptionID string, authorizer autorest.Authorizer) VaultsClient {
client := mgmtkeyvault.NewVaultsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID)
client.Authorizer = authorizer
return &vaultsClient{
VaultsClient: client,
}
}

Просмотреть файл

@ -4,28 +4,15 @@ package billing
// Licensed under the Apache License 2.0.
import (
"bytes"
"context"
"encoding/json"
"net/http"
"os"
"strings"
azstorage "github.com/Azure/azure-sdk-for-go/storage"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/sirupsen/logrus"
"github.com/Azure/ARO-RP/pkg/api"
"github.com/Azure/ARO-RP/pkg/database"
"github.com/Azure/ARO-RP/pkg/database/cosmosdb"
"github.com/Azure/ARO-RP/pkg/env"
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/storage"
"github.com/Azure/ARO-RP/pkg/util/feature"
)
const (
tenantIDMSFT = "72f988bf-86f1-41af-91ab-2d7cd011db47"
tenantIDAME = "33e01921-4d64-4f8c-a055-5bdaffd5e33d"
)
type Manager interface {
@ -34,58 +21,19 @@ type Manager interface {
}
type manager struct {
storageClient *azstorage.Client
billingDB database.Billing
subDB database.Subscriptions
log *logrus.Entry
billingDB database.Billing
log *logrus.Entry
}
func NewManager(env env.Interface, billing database.Billing, sub database.Subscriptions, log *logrus.Entry) (Manager, error) {
storageClient, err := storageClient(env, billing, sub, log)
if err != nil {
return nil, err
}
return &manager{
storageClient: storageClient,
subDB: sub,
billingDB: billing,
log: log,
billingDB: billing,
log: log,
}, nil
}
func storageClient(env env.Interface, billing database.Billing, sub database.Subscriptions, log *logrus.Entry) (*azstorage.Client, error) {
if os.Getenv("BILLING_E2E_STORAGE_ACCOUNT_ID") == "" {
return nil, nil
}
r, err := azure.ParseResourceID(os.Getenv("BILLING_E2E_STORAGE_ACCOUNT_ID"))
if err != nil {
return nil, err
}
localFPAuthorizer, err := env.FPAuthorizer(env.TenantID(), env.Environment().ResourceManagerScope)
if err != nil {
return nil, err
}
e2estorage := storage.NewAccountsClient(env.Environment(), r.SubscriptionID, localFPAuthorizer)
keys, err := e2estorage.ListKeys(context.Background(), r.ResourceGroup, r.ResourceName, "")
if err != nil {
return nil, err
}
client, err := azstorage.NewBasicClient(r.ResourceName, *(*keys.Keys)[0].Value)
if err != nil {
return nil, err
}
return &client, nil
}
func (m *manager) Ensure(ctx context.Context, doc *api.OpenShiftClusterDocument, sub *api.SubscriptionDocument) error {
billingDoc, err := m.billingDB.Create(ctx, &api.BillingDocument{
_, err := m.billingDB.Create(ctx, &api.BillingDocument{
ID: doc.ID,
Key: doc.Key,
ClusterResourceGroupIDKey: doc.ClusterResourceGroupIDKey,
@ -104,16 +52,12 @@ func (m *manager) Ensure(ctx context.Context, doc *api.OpenShiftClusterDocument,
return err
}
if e2eErr := m.createOrUpdateE2EBlob(ctx, billingDoc); e2eErr != nil {
m.log.Warnf("createOrUpdateE2EBlob failed: %s", e2eErr)
}
return nil
}
func (m *manager) Delete(ctx context.Context, doc *api.OpenShiftClusterDocument) error {
m.log.Printf("updating billing record with deletion time")
billingDoc, err := m.billingDB.MarkForDeletion(ctx, doc.ID)
_, err := m.billingDB.MarkForDeletion(ctx, doc.ID)
if cosmosdb.IsErrorStatusCode(err, http.StatusNotFound) {
return nil
}
@ -121,67 +65,5 @@ func (m *manager) Delete(ctx context.Context, doc *api.OpenShiftClusterDocument)
return err
}
if e2eErr := m.createOrUpdateE2EBlob(ctx, billingDoc); e2eErr != nil {
// We are not failing the operation if we cannot write to e2e storage account, just warning
m.log.Warnf("createOrUpdateE2EBlob failed: %s", e2eErr)
}
return nil
}
// isSubscriptionRegisteredForE2E returns true if the subscription has the
// "Microsoft.RedHatOpenShift/SaveAROTestConfig" feature registered
func isSubscriptionRegisteredForE2E(sub *api.SubscriptionProperties) bool {
if sub.TenantID == tenantIDMSFT || sub.TenantID == tenantIDAME {
return feature.IsRegisteredForFeature(sub, api.FeatureFlagSaveAROTestConfig)
}
return false
}
// createOrUpdateE2Eblob create a copy of the billing document in the e2e
// storage account. This is used later on by the billing e2e
func (m *manager) createOrUpdateE2EBlob(ctx context.Context, doc *api.BillingDocument) error {
//skip updating the storage account if this is a dev scenario
if m.storageClient == nil {
return nil
}
// Validate if E2E Feature is registered
resource, err := azure.ParseResourceID(doc.Key)
if err != nil {
return err
}
subscriptionDoc, err := m.subDB.Get(ctx, resource.SubscriptionID)
if err != nil {
return err
}
if !isSubscriptionRegisteredForE2E(subscriptionDoc.Subscription.Properties) {
return nil
}
blobclient := m.storageClient.GetBlobService()
containerName := strings.ToLower("bill-" + doc.Billing.Location + "-" + resource.ResourceGroup + "-" + resource.ResourceName)
if len(containerName) > 63 {
containerName = containerName[:63]
}
// The following is added to get rid of the '-' at the end in order to avoid an invalid container name.
containerName = strings.TrimSuffix(containerName, "-")
containerRef := blobclient.GetContainerReference(containerName)
_, err = containerRef.CreateIfNotExists(nil)
if err != nil {
return err
}
blobRef := containerRef.GetBlobReference("billingentity")
b, err := json.Marshal(doc)
if err != nil {
return err
}
return blobRef.CreateBlockBlobFromReader(bytes.NewReader(b), nil)
}

Просмотреть файл

@ -19,101 +19,6 @@ import (
utilerror "github.com/Azure/ARO-RP/test/util/error"
)
func TestIsSubscriptionRegisteredForE2E(t *testing.T) {
const tenantID = "11111111-1111-1111-1111-111111111111"
for _, tt := range []struct {
name string
sub api.SubscriptionProperties
want bool
}{
{
name: "empty",
},
{
name: "sub without feature flag registered and not internal tenant",
sub: api.SubscriptionProperties{
TenantID: tenantID,
RegisteredFeatures: []api.RegisteredFeatureProfile{
{
Name: "RandomFeature",
State: "Registered",
},
},
},
},
{
name: "sub with feature flag registered and not internal tenant",
sub: api.SubscriptionProperties{
TenantID: tenantID,
RegisteredFeatures: []api.RegisteredFeatureProfile{
{
Name: api.FeatureFlagSaveAROTestConfig,
State: "Registered",
},
},
},
},
{
name: "AME internal tenant and feature flag not registered",
sub: api.SubscriptionProperties{
TenantID: tenantIDAME,
RegisteredFeatures: []api.RegisteredFeatureProfile{
{
Name: "RandomFeature",
State: "Registered",
},
},
},
},
{
name: "MSFT internal tenant and feature flag not registered",
sub: api.SubscriptionProperties{
TenantID: tenantIDMSFT,
RegisteredFeatures: []api.RegisteredFeatureProfile{
{
Name: "RandomFeature",
State: "Registered",
},
},
},
},
{
name: "AME internal tenant and feature flag registered",
sub: api.SubscriptionProperties{
TenantID: tenantIDAME,
RegisteredFeatures: []api.RegisteredFeatureProfile{
{
Name: api.FeatureFlagSaveAROTestConfig,
State: "Registered",
},
},
},
want: true,
},
{
name: "MSFT internal tenant and feature flag registered",
sub: api.SubscriptionProperties{
TenantID: tenantIDMSFT,
RegisteredFeatures: []api.RegisteredFeatureProfile{
{
Name: api.FeatureFlagSaveAROTestConfig,
State: "Registered",
},
},
},
want: true,
},
} {
t.Run(tt.name, func(t *testing.T) {
got := isSubscriptionRegisteredForE2E(&tt.sub)
if got != tt.want {
t.Error(got)
}
})
}
}
func TestDelete(t *testing.T) {
ctx := context.Background()
@ -220,7 +125,6 @@ func TestDelete(t *testing.T) {
m := &manager{
log: log,
billingDB: billingDatabase,
subDB: subscriptionsDatabase,
}
err = m.Delete(ctx, &api.OpenShiftClusterDocument{ID: docID})
@ -279,12 +183,6 @@ func TestEnsure(t *testing.T) {
ID: subID,
Subscription: &api.Subscription{
Properties: &api.SubscriptionProperties{
RegisteredFeatures: []api.RegisteredFeatureProfile{
{
Name: api.FeatureFlagSaveAROTestConfig,
State: "NotRegistered",
},
},
TenantID: tenantID,
},
},
@ -321,12 +219,6 @@ func TestEnsure(t *testing.T) {
ID: subID,
Subscription: &api.Subscription{
Properties: &api.SubscriptionProperties{
RegisteredFeatures: []api.RegisteredFeatureProfile{
{
Name: api.FeatureFlagSaveAROTestConfig,
State: "NotRegistered",
},
},
TenantID: tenantID,
},
},
@ -353,12 +245,6 @@ func TestEnsure(t *testing.T) {
ID: subID,
Subscription: &api.Subscription{
Properties: &api.SubscriptionProperties{
RegisteredFeatures: []api.RegisteredFeatureProfile{
{
Name: api.FeatureFlagSaveAROTestConfig,
State: "NotRegistered",
},
},
TenantID: tenantID,
},
},
@ -408,7 +294,6 @@ func TestEnsure(t *testing.T) {
m := &manager{
log: log,
billingDB: billingDatabase,
subDB: subscriptionsDatabase,
}
doc, err := openShiftClusterDatabase.Get(ctx, strings.ToLower(testdatabase.GetResourcePath(subID, "resourceName")))

Просмотреть файл

@ -45,7 +45,7 @@ func TestEnsureDeleted(t *testing.T) {
})
client := testclienthelper.NewHookingClient(builder.Build()).
WithDeleteHook(func(obj client.Object) error {
WithPreDeleteHook(func(obj client.Object) error {
if obj.GetName() == "test-name-2" {
return fmt.Errorf("error on %s", obj.GetName())
}
@ -70,7 +70,7 @@ func TestEnsureDeleted(t *testing.T) {
Namespace: "test-ns-2",
})
if err == nil {
t.Errorf("function should handle failure response (non-404) correctly")
t.Error(fmt.Errorf("function should handle failure response (non-404) correctly: %w", err))
}
err = ch.EnsureDeleted(ctx, schema.GroupVersionKind{Group: "core", Version: "v1", Kind: "ConfigMap"},

Просмотреть файл

@ -8,6 +8,7 @@ import (
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"math/rand"
"net/http"
@ -15,8 +16,10 @@ import (
"strings"
"time"
armsdk "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
mgmtkeyvault "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2019-09-01/keyvault"
sdkkeyvault "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault"
mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network"
mgmtauthorization "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-09-01-preview/authorization"
mgmtfeatures "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features"
@ -34,9 +37,9 @@ import (
"github.com/Azure/ARO-RP/pkg/deploy/generator"
"github.com/Azure/ARO-RP/pkg/env"
"github.com/Azure/ARO-RP/pkg/util/arm"
"github.com/Azure/ARO-RP/pkg/util/azureclient/azuresdk/armkeyvault"
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/authorization"
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/features"
keyvaultclient "github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/keyvault"
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/network"
redhatopenshift20200430 "github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/redhatopenshift/2020-04-30/redhatopenshift"
redhatopenshift20210901preview "github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/redhatopenshift/2021-09-01-preview/redhatopenshift"
@ -67,20 +70,7 @@ type Cluster struct {
roleassignments authorization.RoleAssignmentsClient
peerings network.VirtualNetworkPeeringsClient
ciParentVnetPeerings network.VirtualNetworkPeeringsClient
vaultsClient keyvaultclient.VaultsClient
}
type errors []error
func (errs errors) Error() string {
var sb strings.Builder
for _, err := range errs {
sb.WriteString(err.Error())
sb.WriteByte('\n')
}
return sb.String()
vaultsClient armkeyvault.VaultsClient
}
func New(log *logrus.Entry, environment env.Core, ci bool) (*Cluster, error) {
@ -91,6 +81,7 @@ func New(log *logrus.Entry, environment env.Core, ci bool) (*Cluster, error) {
}
options := environment.Environment().EnvironmentCredentialOptions()
spTokenCredential, err := azidentity.NewEnvironmentCredential(options)
if err != nil {
return nil, err
@ -104,6 +95,17 @@ func New(log *logrus.Entry, environment env.Core, ci bool) (*Cluster, error) {
scopes := []string{environment.Environment().ResourceManagerScope}
authorizer := azidext.NewTokenCredentialAdapter(spTokenCredential, scopes)
armOption := armsdk.ClientOptions{
ClientOptions: policy.ClientOptions{
Cloud: options.Cloud,
},
}
vaultClient, err := armkeyvault.NewVaultsClient(environment.SubscriptionID(), spTokenCredential, &armOption)
if err != nil {
return nil, err
}
c := &Cluster{
log: log,
env: environment,
@ -121,7 +123,7 @@ func New(log *logrus.Entry, environment env.Core, ci bool) (*Cluster, error) {
routetables: network.NewRouteTablesClient(environment.Environment(), environment.SubscriptionID(), authorizer),
roleassignments: authorization.NewRoleAssignmentsClient(environment.Environment(), environment.SubscriptionID(), authorizer),
peerings: network.NewVirtualNetworkPeeringsClient(environment.Environment(), environment.SubscriptionID(), authorizer),
vaultsClient: keyvaultclient.NewVaultsClient(environment.Environment(), environment.SubscriptionID(), authorizer),
vaultsClient: vaultClient,
}
if ci && env.IsLocalDevelopmentMode() {
@ -232,7 +234,8 @@ func (c *Cluster) Create(ctx context.Context, vnetResourceGroup, clusterName str
if c.ci {
// name is limited to 24 characters, but must be globally unique, so we generate one and try if it is available
kvName = "kv-" + uuid.DefaultGenerator.Generate()[:21]
result, err := c.vaultsClient.CheckNameAvailability(ctx, mgmtkeyvault.VaultCheckNameAvailabilityParameters{Name: &kvName, Type: to.StringPtr("Microsoft.KeyVault/vaults")})
result, err := c.vaultsClient.CheckNameAvailability(ctx, sdkkeyvault.VaultCheckNameAvailabilityParameters{Name: &kvName, Type: to.StringPtr("Microsoft.KeyVault/vaults")}, nil)
if err != nil {
return err
}
@ -381,75 +384,28 @@ func (c *Cluster) generateSubnets() (vnetPrefix string, masterSubnet string, wor
}
func (c *Cluster) Delete(ctx context.Context, vnetResourceGroup, clusterName string) error {
var errs errors
var errs []error
oc, err := c.openshiftclustersv20200430.Get(ctx, vnetResourceGroup, clusterName)
if err == nil {
c.log.Print("deleting role assignments")
err = c.deleteRoleAssignments(ctx, vnetResourceGroup, *oc.OpenShiftClusterProperties.ServicePrincipalProfile.ClientID)
if err != nil {
errs = append(errs, err)
}
c.log.Print("deleting cluster")
err = c.openshiftclustersv20200430.DeleteAndWait(ctx, vnetResourceGroup, clusterName)
if err != nil {
errs = append(errs, err)
}
}
if c.ci {
_, err = c.groups.Get(ctx, vnetResourceGroup)
if err == nil {
c.log.Print("deleting resource group")
err = c.groups.DeleteAndWait(ctx, vnetResourceGroup)
if err != nil {
errs = append(errs, err)
}
}
// Only delete peering if CI=true and RP_MODE=development
if env.IsLocalDevelopmentMode() {
r, err := azure.ParseResourceID(c.ciParentVnet)
if err == nil {
err = c.ciParentVnetPeerings.DeleteAndWait(ctx, r.ResourceGroup, r.ResourceName, vnetResourceGroup+"-peer")
}
if err != nil {
errs = append(errs, err)
}
}
} else {
// Deleting the deployment does not clean up the associated resources
c.log.Info("deleting deployment")
err = c.deployments.DeleteAndWait(ctx, vnetResourceGroup, clusterName)
if err != nil {
errs = append(errs, err)
}
c.log.Info("deleting master/worker subnets")
err = c.subnets.DeleteAndWait(ctx, vnetResourceGroup, "dev-vnet", clusterName+"-master")
if err != nil {
errs = append(errs, err)
}
err = c.subnets.DeleteAndWait(ctx, vnetResourceGroup, "dev-vnet", clusterName+"-worker")
if err != nil {
errs = append(errs, err)
}
c.log.Info("deleting route table")
err = c.routetables.DeleteAndWait(ctx, vnetResourceGroup, clusterName+"-rt")
if err != nil {
errs = append(errs, err)
}
switch {
case c.ci && env.IsLocalDevelopmentMode(): // PR E2E
errs = append(errs,
c.deleteCluster(ctx, vnetResourceGroup, clusterName),
c.deleteClusterResourceGroup(ctx, vnetResourceGroup),
c.deleteVnetPeerings(ctx, vnetResourceGroup),
)
case c.ci: // Prod E2E
errs = append(errs, c.deleteClusterResourceGroup(ctx, vnetResourceGroup))
default:
errs = append(errs,
c.deleteRoleAssignments(ctx, vnetResourceGroup, clusterName),
c.deleteCluster(ctx, vnetResourceGroup, clusterName),
c.deleteDeployment(ctx, vnetResourceGroup, clusterName), // Deleting the deployment does not clean up the associated resources
c.deleteVnetResources(ctx, vnetResourceGroup, "dev-vnet", clusterName),
)
}
c.log.Info("done")
if errs != nil {
return errs // https://golang.org/doc/faq#nil_error
}
return nil
return errors.Join(errs...)
}
// createCluster created new clusters, based on where it is running.
@ -647,10 +603,15 @@ func (c *Cluster) fixupNSGs(ctx context.Context, vnetResourceGroup, clusterName
return nil
}
func (c *Cluster) deleteRoleAssignments(ctx context.Context, vnetResourceGroup, appID string) error {
spObjID, err := utilgraph.GetServicePrincipalIDByAppID(ctx, c.spGraphClient, appID)
func (c *Cluster) deleteRoleAssignments(ctx context.Context, vnetResourceGroup, clusterName string) error {
c.log.Print("deleting role assignments")
oc, err := c.openshiftclustersv20200430.Get(ctx, vnetResourceGroup, clusterName)
if err != nil {
return err
return fmt.Errorf("error getting cluster document: %w", err)
}
spObjID, err := utilgraph.GetServicePrincipalIDByAppID(ctx, c.spGraphClient, *oc.OpenShiftClusterProperties.ServicePrincipalProfile.ClientID)
if err != nil {
return fmt.Errorf("error getting service principal for cluster: %w", err)
}
if spObjID == nil {
return nil
@ -658,7 +619,7 @@ func (c *Cluster) deleteRoleAssignments(ctx context.Context, vnetResourceGroup,
roleAssignments, err := c.roleassignments.ListForResourceGroup(ctx, vnetResourceGroup, fmt.Sprintf("principalId eq '%s'", *spObjID))
if err != nil {
return err
return fmt.Errorf("error listing role assignments for service principal: %w", err)
}
for _, roleAssignment := range roleAssignments {
@ -670,7 +631,7 @@ func (c *Cluster) deleteRoleAssignments(ctx context.Context, vnetResourceGroup,
c.log.Infof("deleting role assignment %s", *roleAssignment.Name)
_, err = c.roleassignments.Delete(ctx, *roleAssignment.Scope, *roleAssignment.Name)
if err != nil {
return err
return fmt.Errorf("error deleting role assignment %s: %w", *roleAssignment.Name, err)
}
}
}
@ -678,6 +639,71 @@ func (c *Cluster) deleteRoleAssignments(ctx context.Context, vnetResourceGroup,
return nil
}
func (c *Cluster) deleteCluster(ctx context.Context, resourceGroup, clusterName string) error {
c.log.Printf("deleting cluster %s", clusterName)
if err := c.openshiftclustersv20200430.DeleteAndWait(ctx, resourceGroup, clusterName); err != nil {
return fmt.Errorf("error deleting cluster %s: %w", clusterName, err)
}
return nil
}
func (c *Cluster) deleteClusterResourceGroup(ctx context.Context, resourceGroup string) error {
if _, err := c.groups.Get(ctx, resourceGroup); err != nil {
c.log.Printf("error getting resource group %s, skipping deletion: %v", resourceGroup, err)
return nil
}
c.log.Printf("deleting resource group %s", resourceGroup)
if err := c.groups.DeleteAndWait(ctx, resourceGroup); err != nil {
return fmt.Errorf("error deleting resource group: %w", err)
}
return nil
}
func (c *Cluster) deleteVnetPeerings(ctx context.Context, resourceGroup string) error {
r, err := azure.ParseResourceID(c.ciParentVnet)
if err == nil {
err = c.ciParentVnetPeerings.DeleteAndWait(ctx, r.ResourceGroup, r.ResourceName, resourceGroup+"-peer")
}
if err != nil {
return fmt.Errorf("error deleting vnet peerings: %w", err)
}
return nil
}
func (c *Cluster) deleteDeployment(ctx context.Context, resourceGroup, clusterName string) error {
c.log.Info("deleting deployment")
if err := c.deployments.DeleteAndWait(ctx, resourceGroup, clusterName); err != nil {
return fmt.Errorf("error deleting deployment: %w", err)
}
return nil
}
func (c *Cluster) deleteVnetResources(ctx context.Context, resourceGroup, vnetName, clusterName string) error {
var errs []error
c.log.Info("deleting master/worker subnets")
if err := c.subnets.DeleteAndWait(ctx, resourceGroup, vnetName, clusterName+"-master"); err != nil {
c.log.Errorf("error when deleting master subnet: %v", err)
errs = append(errs, err)
}
if err := c.subnets.DeleteAndWait(ctx, resourceGroup, vnetName, clusterName+"-worker"); err != nil {
c.log.Errorf("error when deleting worker subnet: %v", err)
errs = append(errs, err)
}
c.log.Info("deleting route table")
if err := c.routetables.DeleteAndWait(ctx, resourceGroup, clusterName+"-rt"); err != nil {
c.log.Errorf("error when deleting route table: %v", err)
errs = append(errs, err)
}
return errors.Join(errs...)
}
func (c *Cluster) peerSubnetsToCI(ctx context.Context, vnetResourceGroup, clusterName string) error {
cluster := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/virtualNetworks/dev-vnet", c.env.SubscriptionID(), vnetResourceGroup)

Просмотреть файл

@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/authorization (interfaces: PermissionsClient,RoleAssignmentsClient,DenyAssignmentClient,RoleDefinitionsClient)
// Source: github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/authorization (interfaces: RoleAssignmentsClient,DenyAssignmentClient,RoleDefinitionsClient)
// Package mock_authorization is a generated GoMock package.
package mock_authorization
@ -12,59 +12,6 @@ import (
gomock "github.com/golang/mock/gomock"
)
// MockPermissionsClient is a mock of PermissionsClient interface.
type MockPermissionsClient struct {
ctrl *gomock.Controller
recorder *MockPermissionsClientMockRecorder
}
// MockPermissionsClientMockRecorder is the mock recorder for MockPermissionsClient.
type MockPermissionsClientMockRecorder struct {
mock *MockPermissionsClient
}
// NewMockPermissionsClient creates a new mock instance.
func NewMockPermissionsClient(ctrl *gomock.Controller) *MockPermissionsClient {
mock := &MockPermissionsClient{ctrl: ctrl}
mock.recorder = &MockPermissionsClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockPermissionsClient) EXPECT() *MockPermissionsClientMockRecorder {
return m.recorder
}
// ListForResource mocks base method.
func (m *MockPermissionsClient) ListForResource(arg0 context.Context, arg1, arg2, arg3, arg4, arg5 string) ([]authorization.Permission, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListForResource", arg0, arg1, arg2, arg3, arg4, arg5)
ret0, _ := ret[0].([]authorization.Permission)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ListForResource indicates an expected call of ListForResource.
func (mr *MockPermissionsClientMockRecorder) ListForResource(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListForResource", reflect.TypeOf((*MockPermissionsClient)(nil).ListForResource), arg0, arg1, arg2, arg3, arg4, arg5)
}
// ListForResourceGroup mocks base method.
func (m *MockPermissionsClient) ListForResourceGroup(arg0 context.Context, arg1 string) ([]authorization.Permission, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListForResourceGroup", arg0, arg1)
ret0, _ := ret[0].([]authorization.Permission)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ListForResourceGroup indicates an expected call of ListForResourceGroup.
func (mr *MockPermissionsClientMockRecorder) ListForResourceGroup(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListForResourceGroup", reflect.TypeOf((*MockPermissionsClient)(nil).ListForResourceGroup), arg0, arg1)
}
// MockRoleAssignmentsClient is a mock of RoleAssignmentsClient interface.
type MockRoleAssignmentsClient struct {
ctrl *gomock.Controller

Просмотреть файл

@ -1,52 +0,0 @@
package permissions
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"regexp"
"strings"
mgmtauthorization "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-09-01-preview/authorization"
)
// CanDoAction returns true if a given action is granted by a set of permissions
func CanDoAction(ps []mgmtauthorization.Permission, a string) (bool, error) {
for _, p := range ps {
var matched bool
for _, action := range *p.Actions {
action := regexp.QuoteMeta(action)
action = "(?i)^" + strings.ReplaceAll(action, `\*`, ".*") + "$"
rx, err := regexp.Compile(action)
if err != nil {
return false, err
}
if rx.MatchString(a) {
matched = true
break
}
}
if !matched {
continue
}
for _, notAction := range *p.NotActions {
notAction := regexp.QuoteMeta(notAction)
notAction = "(?i)^" + strings.ReplaceAll(notAction, `\*`, ".*") + "$"
rx, err := regexp.Compile(notAction)
if err != nil {
return false, err
}
if rx.MatchString(a) {
matched = false
break
}
}
if matched {
return true, nil
}
}
return false, nil
}

Просмотреть файл

@ -1,92 +0,0 @@
package permissions
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"testing"
mgmtauthorization "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-09-01-preview/authorization"
)
func TestCanDoAction(t *testing.T) {
tests := []struct {
name string
permissions []mgmtauthorization.Permission
action string
want bool
}{
{
name: "empty permissions list",
action: "Microsoft.Network/virtualNetworks/subnets/join/action",
},
{
name: "has permission - exact",
permissions: []mgmtauthorization.Permission{
{
Actions: &[]string{"Microsoft.Compute/virtualMachines/*"},
NotActions: &[]string{},
},
{
Actions: &[]string{"Microsoft.Network/virtualNetworks/subnets/join/action"},
NotActions: &[]string{},
},
},
action: "Microsoft.Network/virtualNetworks/subnets/join/action",
want: true,
},
{
name: "has permission - wildcard",
permissions: []mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Network/virtualNetworks/subnets/*/action"},
NotActions: &[]string{},
}},
action: "Microsoft.Network/virtualNetworks/subnets/join/action",
want: true,
},
{
name: "has permission - exact, conflict",
permissions: []mgmtauthorization.Permission{
{
Actions: &[]string{"Microsoft.Network/virtualNetworks/subnets/join/action"},
NotActions: &[]string{},
},
{
Actions: &[]string{},
NotActions: &[]string{"Microsoft.Network/virtualNetworks/subnets/join/action"},
},
},
action: "Microsoft.Network/virtualNetworks/subnets/join/action",
want: true,
},
{
name: "has permission excluded - exact",
permissions: []mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Network/*"},
NotActions: &[]string{"Microsoft.Network/virtualNetworks/subnets/join/action"},
}},
action: "Microsoft.Network/virtualNetworks/subnets/join/action",
},
{
name: "has permission excluded - wildcard",
permissions: []mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Network/*"},
NotActions: &[]string{"Microsoft.Network/virtualNetworks/subnets/*/action"},
}},
action: "Microsoft.Network/virtualNetworks/subnets/join/action",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ok, err := CanDoAction(test.permissions, test.action)
if err != nil {
t.Fatalf("unexpected error: %#v", err)
}
if ok != test.want {
t.Errorf("expected result %#v, got %#v", test.want, ok)
}
})
}
}

Просмотреть файл

@ -11,7 +11,6 @@ import (
"testing"
mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute"
mgmtauthorization "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-09-01-preview/authorization"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/to"
@ -19,7 +18,10 @@ import (
"github.com/sirupsen/logrus"
"github.com/Azure/ARO-RP/pkg/api"
mock_authorization "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/mgmt/authorization"
"github.com/Azure/ARO-RP/pkg/util/azureclient"
"github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp"
mock_remotepdp "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/authz/remotepdp"
mock_azcore "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/azuresdk/azcore"
mock_compute "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/mgmt/compute"
utilerror "github.com/Azure/ARO-RP/test/util/error"
)
@ -44,10 +46,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
t.Run(string(authorizerType), func(t *testing.T) {
for _, tt := range []struct {
name string
oc *api.OpenShiftCluster
mocks func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc)
wantErr string
name string
oc *api.OpenShiftCluster
actionInfos []remotepdp.ActionInfo
mocks func(*mock_compute.MockDiskEncryptionSetsClient, *mock_remotepdp.MockRemotePDPClient, *mock_azcore.MockTokenCredential, context.CancelFunc)
wantErr string
}{
{
name: "no disk encryption set provided",
@ -66,13 +69,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
}},
},
},
mocks: func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc) {
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.Provider, "", fakeDesR1.ResourceType, fakeDesR1.ResourceName).
Return([]mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Compute/diskEncryptionSets/read"},
NotActions: &[]string{},
}}, nil)
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
mockTokenCredential(tokenCred)
pdpClient.EXPECT().
CheckAccess(gomock.Any(), gomock.Any()).
Return(validDiskEncryptionAuthorizationDecision, nil)
diskEncryptionSets.EXPECT().
Get(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.ResourceName).
Return(mgmtcompute.DiskEncryptionSet{Location: to.StringPtr("eastus")}, nil)
@ -91,13 +92,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
}},
},
},
mocks: func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc) {
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.Provider, "", fakeDesR1.ResourceType, fakeDesR1.ResourceName).
Return([]mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Compute/diskEncryptionSets/read"},
NotActions: &[]string{},
}}, nil)
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
mockTokenCredential(tokenCred)
pdpClient.EXPECT().
CheckAccess(gomock.Any(), gomock.Any()).
Return(validDiskEncryptionAuthorizationDecision, nil)
diskEncryptionSets.EXPECT().
Get(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.ResourceName).
Return(mgmtcompute.DiskEncryptionSet{Location: to.StringPtr("eastus")}, nil)
@ -116,19 +115,21 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
}},
},
},
mocks: func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc) {
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.Provider, "", fakeDesR1.ResourceType, fakeDesR1.ResourceName).
Return([]mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Compute/diskEncryptionSets/read"},
NotActions: &[]string{},
}}, nil)
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR2.ResourceGroup, fakeDesR2.Provider, "", fakeDesR2.ResourceType, fakeDesR2.ResourceName).
Return([]mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Compute/diskEncryptionSets/read"},
NotActions: &[]string{},
}}, nil)
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
mockTokenCredential(tokenCred)
pdpClient.EXPECT().
CheckAccess(gomock.Any(), gomock.Any()).
DoAndReturn(func(_ context.Context, authReq remotepdp.AuthorizationRequest) (*remotepdp.AuthorizationDecisionResponse, error) {
cancel() // wait.PollImmediateUntil will always be invoked at least once
switch authReq.Resource.Id {
case fakeDesR1.String():
return validDiskEncryptionAuthorizationDecision, nil
case fakeDesR2.String():
return validDiskEncryptionAuthorizationDecision, nil
}
return invalidDiskEncryptionAuthorizationDecisionsReadNotAllowed, nil
},
).AnyTimes()
diskEncryptionSets.EXPECT().
Get(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.ResourceName).
Return(mgmtcompute.DiskEncryptionSet{Location: to.StringPtr("eastus")}, nil)
@ -150,13 +151,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
}},
},
},
mocks: func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc) {
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.Provider, "", fakeDesR1.ResourceType, fakeDesR1.ResourceName).
Return([]mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Compute/diskEncryptionSets/read"},
NotActions: &[]string{},
}}, nil)
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
mockTokenCredential(tokenCred)
pdpClient.EXPECT().
CheckAccess(gomock.Any(), gomock.Any()).
Return(validDiskEncryptionAuthorizationDecision, nil)
diskEncryptionSets.EXPECT().
Get(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.ResourceName).
Return(mgmtcompute.DiskEncryptionSet{}, autorest.DetailedError{StatusCode: http.StatusNotFound})
@ -176,9 +175,10 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
}},
},
},
mocks: func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc) {
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.Provider, "", fakeDesR1.ResourceType, fakeDesR1.ResourceName).
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
mockTokenCredential(tokenCred)
pdpClient.EXPECT().
CheckAccess(gomock.Any(), gomock.Any()).
Return(nil, errors.New("fakeerr"))
},
wantErr: "fakeerr",
@ -196,13 +196,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
}},
},
},
mocks: func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc) {
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.Provider, "", fakeDesR1.ResourceType, fakeDesR1.ResourceName).
Return([]mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Compute/diskEncryptionSets/read"},
NotActions: &[]string{},
}}, nil)
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
mockTokenCredential(tokenCred)
pdpClient.EXPECT().
CheckAccess(gomock.Any(), gomock.Any()).
Return(validDiskEncryptionAuthorizationDecision, nil)
diskEncryptionSets.EXPECT().
Get(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.ResourceName).
Return(mgmtcompute.DiskEncryptionSet{}, errors.New("fakeerr"))
@ -222,10 +220,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
}},
},
},
mocks: func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc) {
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.Provider, "", fakeDesR1.ResourceType, fakeDesR1.ResourceName).
Do(func(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) {
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
mockTokenCredential(tokenCred)
pdpClient.EXPECT().
CheckAccess(gomock.Any(), gomock.Any()).
Do(func(arg0, arg1 interface{}) {
cancel()
})
},
@ -244,16 +243,21 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
}},
},
},
mocks: func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc) {
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.Provider, "", fakeDesR1.ResourceType, fakeDesR1.ResourceName).
Return([]mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Compute/diskEncryptionSets/read"},
NotActions: &[]string{},
}}, nil)
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR2.ResourceGroup, fakeDesR2.Provider, "", fakeDesR2.ResourceType, fakeDesR2.ResourceName).
Return(nil, autorest.DetailedError{StatusCode: http.StatusNotFound})
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
mockTokenCredential(tokenCred)
pdpClient.EXPECT().
CheckAccess(gomock.Any(), gomock.Any()).
DoAndReturn(func(_ context.Context, authReq remotepdp.AuthorizationRequest) (*remotepdp.AuthorizationDecisionResponse, error) {
cancel() // wait.PollImmediateUntil will always be invoked at least once
switch authReq.Resource.Id {
case fakeDesR1.String():
return validDiskEncryptionAuthorizationDecision, nil
case fakeDesR2.String():
return nil, autorest.DetailedError{StatusCode: http.StatusNotFound}
}
return invalidDiskEncryptionAuthorizationDecisionsReadNotAllowed, nil
},
).AnyTimes()
diskEncryptionSets.EXPECT().
Get(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.ResourceName).
Return(mgmtcompute.DiskEncryptionSet{Location: to.StringPtr("eastus")}, nil)
@ -273,13 +277,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
}},
},
},
mocks: func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc) {
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.Provider, "", fakeDesR1.ResourceType, fakeDesR1.ResourceName).
Return([]mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Compute/diskEncryptionSets/read"},
NotActions: &[]string{},
}}, nil)
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
mockTokenCredential(tokenCred)
pdpClient.EXPECT().
CheckAccess(gomock.Any(), gomock.Any()).
Return(validDiskEncryptionAuthorizationDecision, nil)
diskEncryptionSets.EXPECT().
Get(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.ResourceName).
Return(mgmtcompute.DiskEncryptionSet{Location: to.StringPtr("westeurope")}, nil)
@ -294,18 +296,21 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
controller := gomock.NewController(t)
defer controller.Finish()
permissionsClient := mock_authorization.NewMockPermissionsClient(controller)
diskEncryptionSetsClient := mock_compute.NewMockDiskEncryptionSetsClient(controller)
tokenCred := mock_azcore.NewMockTokenCredential(controller)
remotePDPClient := mock_remotepdp.NewMockRemotePDPClient(controller)
if tt.mocks != nil {
tt.mocks(permissionsClient, diskEncryptionSetsClient, cancel)
tt.mocks(diskEncryptionSetsClient, remotePDPClient, tokenCred, cancel)
}
dv := &dynamic{
authorizerType: authorizerType,
log: logrus.NewEntry(logrus.StandardLogger()),
permissions: permissionsClient,
diskEncryptionSets: diskEncryptionSetsClient,
azEnv: &azureclient.PublicCloud,
authorizerType: authorizerType,
log: logrus.NewEntry(logrus.StandardLogger()),
diskEncryptionSets: diskEncryptionSetsClient,
pdpClient: remotePDPClient,
checkAccessSubjectInfoCred: tokenCred,
}
err := dv.ValidateDiskEncryptionSets(ctx, tt.oc)
@ -315,3 +320,22 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
})
}
}
var (
invalidDiskEncryptionAuthorizationDecisionsReadNotAllowed = &remotepdp.AuthorizationDecisionResponse{
Value: []remotepdp.AuthorizationDecision{
{
ActionId: "Microsoft.Compute/diskEncryptionSets/read",
AccessDecision: remotepdp.NotAllowed,
},
},
}
validDiskEncryptionAuthorizationDecision = &remotepdp.AuthorizationDecisionResponse{
Value: []remotepdp.AuthorizationDecision{
{
ActionId: "Microsoft.Compute/diskEncryptionSets/read",
AccessDecision: remotepdp.Allowed,
},
},
}
)

Просмотреть файл

@ -25,11 +25,8 @@ import (
"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/mgmt/authorization"
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/compute"
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/network"
"github.com/Azure/ARO-RP/pkg/util/permissions"
"github.com/Azure/ARO-RP/pkg/util/steps"
"github.com/Azure/ARO-RP/pkg/util/token"
)
@ -87,7 +84,6 @@ type dynamic struct {
env env.Interface
azEnv *azureclient.AROEnvironment
permissions authorization.PermissionsClient
virtualNetworks virtualNetworksGetClient
diskEncryptionSets compute.DiskEncryptionSetsClient
resourceSkusClient compute.ResourceSkusClient
@ -125,7 +121,6 @@ func NewValidator(
spComputeUsage: compute.NewUsageClient(azEnv, subscriptionID, authorizer),
spNetworkUsage: network.NewUsageClient(azEnv, subscriptionID, authorizer),
permissions: authorization.NewPermissionsClient(azEnv, subscriptionID, authorizer),
virtualNetworks: newVirtualNetworksCache(
network.NewVirtualNetworksClient(azEnv, subscriptionID, authorizer),
),
@ -397,12 +392,8 @@ func (dv *dynamic) validateActions(ctx context.Context, r *azure.Resource, actio
defer cancel()
c := closure{dv: dv, ctx: ctx, resource: r, actions: actions}
conditionalFunc := c.usingListPermissions
if dv.pdpClient != nil {
conditionalFunc = c.usingCheckAccessV2
}
return wait.PollImmediateUntil(30*time.Second, conditionalFunc, timeoutCtx.Done())
return wait.PollImmediateUntil(30*time.Second, c.usingCheckAccessV2, timeoutCtx.Done())
}
// closure is the closure used in PollImmediateUntil's ConditionalFunc
@ -414,47 +405,8 @@ type closure struct {
oid *string
}
// usingListPermissions is how the current check is done
func (c closure) usingListPermissions() (bool, error) {
c.dv.log.Debug("retry validateActions with ListPermissions")
perms, err := c.dv.permissions.ListForResource(
c.ctx,
c.resource.ResourceGroup,
c.resource.Provider,
"",
c.resource.ResourceType,
c.resource.ResourceName,
)
if err != nil {
return false, err
}
// If we get a StatusForbidden, try refreshing the SP (since with a
// brand-new SP it might take time to propagate)
if detailedErr, ok := err.(autorest.DetailedError); ok &&
detailedErr.StatusCode == http.StatusForbidden {
return false, steps.ErrWantRefresh
}
if err != nil {
return false, err
}
for _, action := range c.actions {
ok, err := permissions.CanDoAction(perms, action)
if !ok || err != nil {
// TODO(jminter): I don't understand if there are genuinely
// cases where CanDoAction can return false then true shortly
// after. I'm a little skeptical; if it can't happen we can
// simplify this code. We should add a metric on this.
return false, err
}
}
return true, nil
}
// usingCheckAccessV2 uses the new RBAC checkAccessV2 API
func (c closure) usingCheckAccessV2() (bool, error) {
// TODO remove this when fully migrated to CheckAccess
c.dv.log.Info("validateActions with CheckAccessV2")
// reusing oid during retries

Просмотреть файл

@ -7,14 +7,11 @@ import (
"context"
"errors"
"fmt"
"net/http"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network"
mgmtauthorization "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-09-01-preview/authorization"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/to"
"github.com/golang/mock/gomock"
@ -25,7 +22,6 @@ import (
"github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp"
mock_remotepdp "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/authz/remotepdp"
mock_azcore "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/azuresdk/azcore"
mock_authorization "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/mgmt/authorization"
mock_network "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/mgmt/network"
utilerror "github.com/Azure/ARO-RP/test/util/error"
)
@ -48,122 +44,6 @@ var (
workerNSGv1 = resourceGroupID + "/providers/Microsoft.Network/networkSecurityGroups/aro-node-nsg"
)
func TestValidateVnetPermissions(t *testing.T) {
ctx := context.Background()
resourceType := "virtualNetworks"
resourceProvider := "Microsoft.Network"
for _, tt := range []struct {
name string
mocks func(*mock_authorization.MockPermissionsClient, context.CancelFunc)
wantErr string
}{
{
name: "pass",
mocks: func(permissionsClient *mock_authorization.MockPermissionsClient, cancel context.CancelFunc) {
permissionsClient.EXPECT().
ListForResource(gomock.Any(), resourceGroupName, resourceProvider, "", resourceType, vnetName).
Return([]mgmtauthorization.Permission{
{
Actions: &[]string{
"Microsoft.Network/virtualNetworks/join/action",
"Microsoft.Network/virtualNetworks/read",
"Microsoft.Network/virtualNetworks/write",
"Microsoft.Network/virtualNetworks/subnets/join/action",
"Microsoft.Network/virtualNetworks/subnets/read",
"Microsoft.Network/virtualNetworks/subnets/write",
},
NotActions: &[]string{},
},
}, nil)
},
},
{
name: "fail: missing permissions",
mocks: func(permissionsClient *mock_authorization.MockPermissionsClient, cancel context.CancelFunc) {
permissionsClient.EXPECT().
ListForResource(gomock.Any(), resourceGroupName, resourceProvider, "", resourceType, vnetName).
Do(func(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) {
cancel()
}).
Return(
[]mgmtauthorization.Permission{
{
Actions: &[]string{},
NotActions: &[]string{},
},
},
nil,
)
},
wantErr: "400: InvalidServicePrincipalPermissions: : The cluster service principal (Application ID: fff51942-b1f9-4119-9453-aaa922259eb7) does not have Network Contributor role on vnet '" + vnetID + "'.",
},
{
name: "fail: not found",
mocks: func(permissionsClient *mock_authorization.MockPermissionsClient, cancel context.CancelFunc) {
permissionsClient.EXPECT().
ListForResource(gomock.Any(), resourceGroupName, resourceProvider, "", resourceType, vnetName).
Do(func(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) {
cancel()
}).
Return(
nil,
autorest.DetailedError{
StatusCode: http.StatusNotFound,
},
)
},
wantErr: "400: InvalidLinkedVNet: : The vnet '" + vnetID + "' could not be found.",
},
{
name: "fail: fp/sp has no permission on the target vnet (forbidden error)",
mocks: func(permissionsClient *mock_authorization.MockPermissionsClient, cancel context.CancelFunc) {
permissionsClient.EXPECT().
ListForResource(gomock.Any(), resourceGroupName, resourceProvider, "", resourceType, vnetName).
Do(func(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) {
cancel()
}).
Return(
nil,
autorest.DetailedError{
StatusCode: http.StatusForbidden,
Message: "some forbidden error on the resource.",
},
)
},
wantErr: "400: InvalidServicePrincipalPermissions: : The cluster service principal (Application ID: fff51942-b1f9-4119-9453-aaa922259eb7) does not have Network Contributor role on vnet '" + vnetID + "'.\nOriginal error message: some forbidden error on the resource.",
},
} {
t.Run(tt.name, func(t *testing.T) {
controller := gomock.NewController(t)
defer controller.Finish()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
permissionsClient := mock_authorization.NewMockPermissionsClient(controller)
tt.mocks(permissionsClient, cancel)
dv := &dynamic{
appID: "fff51942-b1f9-4119-9453-aaa922259eb7",
authorizerType: AuthorizerClusterServicePrincipal,
log: logrus.NewEntry(logrus.StandardLogger()),
permissions: permissionsClient,
}
vnetr, err := azure.ParseResourceID(vnetID)
if err != nil {
t.Fatal(err)
}
err = dv.validateVnetPermissions(ctx, vnetr)
utilerror.AssertErrorMessage(t, err, tt.wantErr)
})
}
}
func TestGetRouteTableID(t *testing.T) {
for _, tt := range []struct {
name string
@ -272,324 +152,6 @@ func TestGetNatGatewayID(t *testing.T) {
}
}
func TestValidateRouteTablesPermissions(t *testing.T) {
ctx := context.Background()
for _, tt := range []struct {
name string
subnet Subnet
permissionMocks func(*mock_authorization.MockPermissionsClient, context.CancelFunc)
vnetMocks func(*mock_network.MockVirtualNetworksClient, mgmtnetwork.VirtualNetwork)
wantErr string
}{
{
name: "fail: failed to get vnet",
subnet: Subnet{ID: masterSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, errors.New("failed to get vnet"))
},
wantErr: "failed to get vnet",
},
{
name: "fail: master subnet doesn't exist",
subnet: Subnet{ID: masterSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
vnet.Subnets = nil
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, nil)
},
wantErr: "400: InvalidLinkedVNet: : The provided subnet '" + masterSubnet + "' could not be found.",
},
{
name: "fail: worker subnet ID doesn't exist",
subnet: Subnet{ID: workerSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
(*vnet.Subnets)[1].ID = to.StringPtr("not valid")
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, nil)
},
wantErr: "400: InvalidLinkedVNet: : The provided subnet '" + workerSubnet + "' could not be found.",
},
{
name: "fail: permissions don't exist",
subnet: Subnet{ID: workerSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, nil)
},
permissionMocks: func(permissionsClient *mock_authorization.MockPermissionsClient, cancel context.CancelFunc) {
permissionsClient.EXPECT().
ListForResource(gomock.Any(), resourceGroupName, "Microsoft.Network", "", "routeTables", gomock.Any()).
Do(func(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) {
cancel()
}).
Return(
[]mgmtauthorization.Permission{
{
Actions: &[]string{},
NotActions: &[]string{},
},
},
nil,
)
},
wantErr: "400: InvalidServicePrincipalPermissions: : The cluster service principal does not have Network Contributor role on route table '" + workerRtID + "'.",
},
{
name: "pass",
subnet: Subnet{ID: masterSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, nil)
},
permissionMocks: func(permissionsClient *mock_authorization.MockPermissionsClient, cancel context.CancelFunc) {
permissionsClient.EXPECT().
ListForResource(gomock.Any(), resourceGroupName, "Microsoft.Network", "", "routeTables", gomock.Any()).
AnyTimes().
Return([]mgmtauthorization.Permission{
{
Actions: &[]string{
"Microsoft.Network/routeTables/join/action",
"Microsoft.Network/routeTables/read",
"Microsoft.Network/routeTables/write",
},
NotActions: &[]string{},
},
}, nil)
},
},
{
name: "pass: no route table to check",
subnet: Subnet{ID: masterSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
(*vnet.Subnets)[0].RouteTable = nil
(*vnet.Subnets)[1].RouteTable = nil
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, nil)
},
},
} {
t.Run(tt.name, func(t *testing.T) {
controller := gomock.NewController(t)
defer controller.Finish()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
permissionsClient := mock_authorization.NewMockPermissionsClient(controller)
vnetClient := mock_network.NewMockVirtualNetworksClient(controller)
vnet := &mgmtnetwork.VirtualNetwork{
ID: &vnetID,
VirtualNetworkPropertiesFormat: &mgmtnetwork.VirtualNetworkPropertiesFormat{
Subnets: &[]mgmtnetwork.Subnet{
{
ID: &masterSubnet,
SubnetPropertiesFormat: &mgmtnetwork.SubnetPropertiesFormat{
RouteTable: &mgmtnetwork.RouteTable{
ID: &masterRtID,
},
},
},
{
ID: &workerSubnet,
SubnetPropertiesFormat: &mgmtnetwork.SubnetPropertiesFormat{
RouteTable: &mgmtnetwork.RouteTable{
ID: &workerRtID,
},
},
},
},
},
}
dv := &dynamic{
authorizerType: AuthorizerClusterServicePrincipal,
log: logrus.NewEntry(logrus.StandardLogger()),
permissions: permissionsClient,
virtualNetworks: vnetClient,
}
if tt.permissionMocks != nil {
tt.permissionMocks(permissionsClient, cancel)
}
if tt.vnetMocks != nil {
tt.vnetMocks(vnetClient, *vnet)
}
err := dv.validateRouteTablePermissions(ctx, tt.subnet)
utilerror.AssertErrorMessage(t, err, tt.wantErr)
})
}
}
func TestValidateNatGatewaysPermissions(t *testing.T) {
ctx := context.Background()
for _, tt := range []struct {
name string
subnet Subnet
permissionMocks func(*mock_authorization.MockPermissionsClient, context.CancelFunc)
vnetMocks func(*mock_network.MockVirtualNetworksClient, mgmtnetwork.VirtualNetwork)
wantErr string
}{
{
name: "fail: failed to get vnet",
subnet: Subnet{ID: masterSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, errors.New("failed to get vnet"))
},
wantErr: "failed to get vnet",
},
{
name: "fail: master subnet doesn't exist",
subnet: Subnet{ID: masterSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
vnet.Subnets = nil
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, nil)
},
wantErr: "400: InvalidLinkedVNet: : The provided subnet '" + masterSubnet + "' could not be found.",
},
{
name: "fail: worker subnet ID doesn't exist",
subnet: Subnet{ID: workerSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
(*vnet.Subnets)[1].ID = to.StringPtr("not valid")
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, nil)
},
wantErr: "400: InvalidLinkedVNet: : The provided subnet '" + workerSubnet + "' could not be found.",
},
{
name: "fail: permissions don't exist",
subnet: Subnet{ID: workerSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, nil)
},
permissionMocks: func(permissionsClient *mock_authorization.MockPermissionsClient, cancel context.CancelFunc) {
permissionsClient.EXPECT().
ListForResource(gomock.Any(), resourceGroupName, "Microsoft.Network", "", "natGateways", gomock.Any()).
Do(func(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) {
cancel()
}).
Return(
[]mgmtauthorization.Permission{
{
Actions: &[]string{},
NotActions: &[]string{},
},
},
nil,
)
},
wantErr: "400: InvalidServicePrincipalPermissions: : The cluster service principal does not have Network Contributor role on nat gateway '" + workerNgID + "'.",
},
{
name: "pass",
subnet: Subnet{ID: masterSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, nil)
},
permissionMocks: func(permissionsClient *mock_authorization.MockPermissionsClient, cancel context.CancelFunc) {
permissionsClient.EXPECT().
ListForResource(gomock.Any(), resourceGroupName, "Microsoft.Network", "", "natGateways", gomock.Any()).
AnyTimes().
Return([]mgmtauthorization.Permission{
{
Actions: &[]string{
"Microsoft.Network/natGateways/join/action",
"Microsoft.Network/natGateways/read",
"Microsoft.Network/natGateways/write",
},
NotActions: &[]string{},
},
}, nil)
},
},
{
name: "pass: no nat gateway to check",
subnet: Subnet{ID: masterSubnet},
vnetMocks: func(vnetClient *mock_network.MockVirtualNetworksClient, vnet mgmtnetwork.VirtualNetwork) {
(*vnet.Subnets)[0].NatGateway = nil
(*vnet.Subnets)[1].NatGateway = nil
vnetClient.EXPECT().
Get(gomock.Any(), resourceGroupName, vnetName, "").
Return(vnet, nil)
},
},
} {
t.Run(tt.name, func(t *testing.T) {
controller := gomock.NewController(t)
defer controller.Finish()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
permissionsClient := mock_authorization.NewMockPermissionsClient(controller)
vnetClient := mock_network.NewMockVirtualNetworksClient(controller)
vnet := &mgmtnetwork.VirtualNetwork{
ID: &vnetID,
VirtualNetworkPropertiesFormat: &mgmtnetwork.VirtualNetworkPropertiesFormat{
Subnets: &[]mgmtnetwork.Subnet{
{
ID: &masterSubnet,
SubnetPropertiesFormat: &mgmtnetwork.SubnetPropertiesFormat{
NatGateway: &mgmtnetwork.SubResource{
ID: &masterNgID,
},
},
},
{
ID: &workerSubnet,
SubnetPropertiesFormat: &mgmtnetwork.SubnetPropertiesFormat{
NatGateway: &mgmtnetwork.SubResource{
ID: &workerNgID,
},
},
},
},
},
}
dv := &dynamic{
authorizerType: AuthorizerClusterServicePrincipal,
log: logrus.NewEntry(logrus.StandardLogger()),
permissions: permissionsClient,
virtualNetworks: vnetClient,
}
if tt.permissionMocks != nil {
tt.permissionMocks(permissionsClient, cancel)
}
if tt.vnetMocks != nil {
tt.vnetMocks(vnetClient, *vnet)
}
err := dv.validateNatGatewayPermissions(ctx, tt.subnet)
utilerror.AssertErrorMessage(t, err, tt.wantErr)
})
}
}
func TestValidateCIDRRanges(t *testing.T) {
ctx := context.Background()
@ -1131,7 +693,7 @@ func mockTokenCredential(tokenCred *mock_azcore.MockTokenCredential) {
Return(mockAccessToken, nil)
}
func TestValidateVnetPermissionsWithCheckAccess(t *testing.T) {
func TestValidateVnetPermissions(t *testing.T) {
ctx := context.Background()
for _, tt := range []struct {
@ -1289,7 +851,7 @@ var (
}
)
func TestValidateRouteTablesPermissionsWithCheckAccess(t *testing.T) {
func TestValidateRouteTablesPermissions(t *testing.T) {
ctx := context.Background()
for _, tt := range []struct {
@ -1504,7 +1066,7 @@ var (
}
)
func TestValidateNatGatewaysPermissionsWithCheckAccess(t *testing.T) {
func TestValidateNatGatewaysPermissions(t *testing.T) {
ctx := context.Background()
for _, tt := range []struct {

Просмотреть файл

@ -19,7 +19,6 @@ 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/feature"
"github.com/Azure/ARO-RP/pkg/validate/dynamic"
)
@ -134,20 +133,12 @@ func (dv *openShiftClusterDynamicValidator) Dynamic(ctx context.Context) error {
return err
}
if useCheckAccess || feature.IsRegisteredForFeature(
dv.subscriptionDoc.Subscription.Properties,
api.FeatureFlagCheckAccessTestToggle,
) {
// TODO remove after successfully migrating to CheckAccess
dv.log.Info("Using CheckAccess instead of ListPermissions")
aroEnv := dv.env.Environment()
pdpClient = remotepdp.NewRemotePDPClient(
fmt.Sprintf(aroEnv.Endpoint, dv.env.Location()),
aroEnv.OAuthScope,
fpClientCred,
)
}
aroEnv := dv.env.Environment()
pdpClient = remotepdp.NewRemotePDPClient(
fmt.Sprintf(aroEnv.Endpoint, dv.env.Location()),
aroEnv.OAuthScope,
fpClientCred,
)
scopes := []string{dv.env.Environment().ResourceManagerScope}
err = ensureAccessTokenClaims(ctx, spClientCred, scopes)

Просмотреть файл

@ -18,59 +18,110 @@ type hookFunc func(obj client.Object) error
type HookingClient struct {
f client.WithWatch
getHook []getFunc
deleteHook []hookFunc
createHook []hookFunc
updateHook []hookFunc
patchHook []hookFunc
preGetHook []getFunc
preDeleteHook []hookFunc
preCreateHook []hookFunc
preUpdateHook []hookFunc
prePatchHook []hookFunc
postGetHook []getFunc
postDeleteHook []hookFunc
postCreateHook []hookFunc
postUpdateHook []hookFunc
postPatchHook []hookFunc
}
var _ client.Client = &HookingClient{}
// NewHookingClient creates a
// NewHookingClient creates a client which allows hooks to be added before and
// after the client event. Errors returned in the hooks are returned to the
// caller directly, to simulate issues such as disconnections or errors.
// Prehooks that cause errors will cause the underlying wrapped client to not be
// called.
func NewHookingClient(c client.WithWatch) *HookingClient {
return &HookingClient{
f: c,
getHook: []getFunc{},
deleteHook: []hookFunc{},
createHook: []hookFunc{},
updateHook: []hookFunc{},
patchHook: []hookFunc{},
f: c,
preGetHook: []getFunc{},
preDeleteHook: []hookFunc{},
preCreateHook: []hookFunc{},
preUpdateHook: []hookFunc{},
prePatchHook: []hookFunc{},
postGetHook: []getFunc{},
postDeleteHook: []hookFunc{},
postCreateHook: []hookFunc{},
postUpdateHook: []hookFunc{},
postPatchHook: []hookFunc{},
}
}
func (c *HookingClient) WithGetHook(f getFunc) *HookingClient {
c.getHook = append(c.getHook, f)
c.postGetHook = append(c.postGetHook, f)
return c
}
func (c *HookingClient) WithDeleteHook(f hookFunc) *HookingClient {
c.deleteHook = append(c.deleteHook, f)
c.postDeleteHook = append(c.postDeleteHook, f)
return c
}
func (c *HookingClient) WithCreateHook(f hookFunc) *HookingClient {
c.createHook = append(c.createHook, f)
c.postCreateHook = append(c.postCreateHook, f)
return c
}
func (c *HookingClient) WithUpdateHook(f hookFunc) *HookingClient {
c.updateHook = append(c.updateHook, f)
c.postUpdateHook = append(c.postUpdateHook, f)
return c
}
func (c *HookingClient) WithPatchHook(f hookFunc) *HookingClient {
c.patchHook = append(c.patchHook, f)
c.postPatchHook = append(c.postPatchHook, f)
return c
}
func (c *HookingClient) WithPreGetHook(f getFunc) *HookingClient {
c.preGetHook = append(c.preGetHook, f)
return c
}
func (c *HookingClient) WithPreDeleteHook(f hookFunc) *HookingClient {
c.preDeleteHook = append(c.preDeleteHook, f)
return c
}
func (c *HookingClient) WithPreCreateHook(f hookFunc) *HookingClient {
c.preCreateHook = append(c.preCreateHook, f)
return c
}
func (c *HookingClient) WithPreUpdateHook(f hookFunc) *HookingClient {
c.preUpdateHook = append(c.preUpdateHook, f)
return c
}
func (c *HookingClient) WithPrePatchHook(f hookFunc) *HookingClient {
c.prePatchHook = append(c.prePatchHook, f)
return c
}
// See [sigs.k8s.io/controller-runtime/pkg/client.Reader.Get]
func (c *HookingClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object) error {
for _, h := range c.getHook {
for _, h := range c.preGetHook {
err := h(key, obj)
if err != nil {
return err
}
}
return c.f.Get(ctx, key, obj)
err := c.f.Get(ctx, key, obj)
if err != nil {
return err
}
for _, h := range c.postGetHook {
err := h(key, obj)
if err != nil {
return err
}
}
return nil
}
// See [sigs.k8s.io/controller-runtime/pkg/client.Reader.List]
@ -85,24 +136,48 @@ func (c *HookingClient) Watch(ctx context.Context, list client.ObjectList, opts
// See [sigs.k8s.io/controller-runtime/pkg/client.Writer.Create]
func (c *HookingClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {
for _, h := range c.createHook {
for _, h := range c.preCreateHook {
err := h(obj)
if err != nil {
return err
}
}
return c.f.Create(ctx, obj, opts...)
err := c.f.Create(ctx, obj, opts...)
if err != nil {
return err
}
for _, h := range c.postCreateHook {
err := h(obj)
if err != nil {
return err
}
}
return nil
}
// See [sigs.k8s.io/controller-runtime/pkg/client.Writer.Delete]
func (c *HookingClient) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error {
for _, h := range c.deleteHook {
for _, h := range c.preDeleteHook {
err := h(obj)
if err != nil {
return err
}
}
return c.f.Delete(ctx, obj, opts...)
err := c.f.Delete(ctx, obj, opts...)
if err != nil {
return err
}
for _, h := range c.postDeleteHook {
err := h(obj)
if err != nil {
return err
}
}
return nil
}
// See [sigs.k8s.io/controller-runtime/pkg/client.Writer.DeleteAllOf]
@ -112,24 +187,48 @@ func (c *HookingClient) DeleteAllOf(ctx context.Context, obj client.Object, opts
// See [sigs.k8s.io/controller-runtime/pkg/client.Writer.Update]
func (c *HookingClient) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error {
for _, h := range c.updateHook {
for _, h := range c.preUpdateHook {
err := h(obj)
if err != nil {
return err
}
}
return c.f.Update(ctx, obj, opts...)
err := c.f.Update(ctx, obj, opts...)
if err != nil {
return err
}
for _, h := range c.postUpdateHook {
err := h(obj)
if err != nil {
return err
}
}
return nil
}
// See [sigs.k8s.io/controller-runtime/pkg/client.Writer.Patch]
func (c *HookingClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
for _, h := range c.patchHook {
for _, h := range c.prePatchHook {
err := h(obj)
if err != nil {
return err
}
}
return c.f.Patch(ctx, obj, patch, opts...)
err := c.f.Patch(ctx, obj, patch, opts...)
if err != nil {
return err
}
for _, h := range c.postPatchHook {
err := h(obj)
if err != nil {
return err
}
}
return nil
}
// See [sigs.k8s.io/controller-runtime/pkg/client.Client.Scheme]

9
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/to/doc.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,9 @@
//go:build go1.18
// +build go1.18
// Copyright 2017 Microsoft Corporation. All rights reserved.
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
// Package to contains various type-conversion helper functions.
package to

21
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/to/to.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
//go:build go1.18
// +build go1.18
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package to
// Ptr returns a pointer to the provided value.
func Ptr[T any](v T) *T {
return &v
}
// SliceOfPtrs returns a slice of *T from the specified values.
func SliceOfPtrs[T any](vv ...T) []*T {
slc := make([]*T, len(vv))
for i := range vv {
slc[i] = Ptr(vv[i])
}
return slc
}

43
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md сгенерированный поставляемый
Просмотреть файл

@ -1,10 +1,53 @@
# Release History
## 1.4.0 (2023-10-10)
### Bugs Fixed
* `ManagedIdentityCredential` will now retry when IMDS responds 410 or 503
## 1.4.0-beta.5 (2023-09-12)
### Features Added
* Service principal credentials can request CAE tokens
### Breaking Changes
> These changes affect only code written against a beta version such as v1.4.0-beta.4
* Whether `GetToken` requests a CAE token is now determined by `TokenRequestOptions.EnableCAE`. Azure
SDK clients which support CAE will set this option automatically. Credentials no longer request CAE
tokens by default or observe the environment variable "AZURE_IDENTITY_DISABLE_CP1".
### Bugs Fixed
* Credential chains such as `DefaultAzureCredential` now try their next credential, if any, when
managed identity authentication fails in a Docker Desktop container
([#21417](https://github.com/Azure/azure-sdk-for-go/issues/21417))
## 1.4.0-beta.4 (2023-08-16)
### Other Changes
* Upgraded dependencies
## 1.3.1 (2023-08-16)
### Other Changes
* Upgraded dependencies
## 1.4.0-beta.3 (2023-08-08)
### Bugs Fixed
* One invocation of `AzureCLICredential.GetToken()` and `OnBehalfOfCredential.GetToken()`
can no longer make two authentication attempts
## 1.4.0-beta.2 (2023-07-14)
### Other Changes
* `DefaultAzureCredentialOptions.TenantID` applies to workload identity authentication
* Upgraded dependencies
## 1.4.0-beta.1 (2023-06-06)
### Other Changes
* Re-enabled CAE support as in v1.3.0-beta.3
## 1.3.0 (2023-05-09)
### Breaking Changes

2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md сгенерированный поставляемый
Просмотреть файл

@ -76,12 +76,14 @@ azlog.SetListener(func(event azlog.Event, s string) {
azlog.SetEvents(azidentity.EventAuthentication)
```
<a id="dac"></a>
## Troubleshoot DefaultAzureCredential authentication issues
| Error |Description| Mitigation |
|---|---|---|
|"DefaultAzureCredential failed to acquire a token"|No credential in the `DefaultAzureCredential` chain provided a token|<ul><li>[Enable logging](#enable-and-configure-logging) to get further diagnostic information.</li><li>Consult the troubleshooting guide for underlying credential types for more information.</li><ul><li>[EnvironmentCredential](#troubleshoot-environmentcredential-authentication-issues)</li><li>[ManagedIdentityCredential](#troubleshoot-managedidentitycredential-authentication-issues)</li><li>[AzureCLICredential](#troubleshoot-azureclicredential-authentication-issues)</li></ul>|
|Error from the client with a status code of 401 or 403|Authentication succeeded but the authorizing Azure service responded with a 401 (Unauthorized), or 403 (Forbidden) status code|<ul><li>[Enable logging](#enable-and-configure-logging) to determine which credential in the chain returned the authenticating token.</li><li>If an unexpected credential is returning a token, check application configuration such as environment variables.</li><li>Ensure the correct role is assigned to the authenticated identity. For example, a service specific role rather than the subscription Owner role.</li></ul>|
|"managed identity timed out"|`DefaultAzureCredential` sets a short timeout on its first managed identity authentication attempt to prevent very long timeouts during local development when no managed identity is available. That timeout causes this error in production when an application requests a token before the hosting environment is ready to provide one.|Use [ManagedIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ManagedIdentityCredential) directly, at least in production. It doesn't set a timeout on its authentication attempts.|
## Troubleshoot EnvironmentCredential authentication issues

98
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go сгенерированный поставляемый
Просмотреть файл

@ -10,12 +10,12 @@ import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"os"
"regexp"
"strings"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
@ -41,65 +41,18 @@ const (
organizationsTenantID = "organizations"
developerSignOnClientID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"
defaultSuffix = "/.default"
tenantIDValidationErr = "invalid tenantID. You can locate your tenantID by following the instructions listed here: https://docs.microsoft.com/partner-center/find-ids-and-domain-names"
)
var (
// capability CP1 indicates the client application is capable of handling CAE claims challenges
cp1 = []string{"CP1"}
// CP1 is disabled until CAE support is added back
disableCP1 = true
cp1 = []string{"CP1"}
errInvalidTenantID = errors.New("invalid tenantID. You can locate your tenantID by following the instructions listed here: https://learn.microsoft.com/partner-center/find-ids-and-domain-names")
)
var getConfidentialClient = func(clientID, tenantID string, cred confidential.Credential, co *azcore.ClientOptions, additionalOpts ...confidential.Option) (confidentialClient, error) {
if !validTenantID(tenantID) {
return confidential.Client{}, errors.New(tenantIDValidationErr)
}
authorityHost, err := setAuthorityHost(co.Cloud)
if err != nil {
return confidential.Client{}, err
}
authority := runtime.JoinPaths(authorityHost, tenantID)
o := []confidential.Option{
confidential.WithAzureRegion(os.Getenv(azureRegionalAuthorityName)),
confidential.WithHTTPClient(newPipelineAdapter(co)),
}
if !disableCP1 {
o = append(o, confidential.WithClientCapabilities(cp1))
}
o = append(o, additionalOpts...)
if strings.ToLower(tenantID) == "adfs" {
o = append(o, confidential.WithInstanceDiscovery(false))
}
return confidential.New(authority, clientID, cred, o...)
}
var getPublicClient = func(clientID, tenantID string, co *azcore.ClientOptions, additionalOpts ...public.Option) (public.Client, error) {
if !validTenantID(tenantID) {
return public.Client{}, errors.New(tenantIDValidationErr)
}
authorityHost, err := setAuthorityHost(co.Cloud)
if err != nil {
return public.Client{}, err
}
o := []public.Option{
public.WithAuthority(runtime.JoinPaths(authorityHost, tenantID)),
public.WithHTTPClient(newPipelineAdapter(co)),
}
if !disableCP1 {
o = append(o, public.WithClientCapabilities(cp1))
}
o = append(o, additionalOpts...)
if strings.ToLower(tenantID) == "adfs" {
o = append(o, public.WithInstanceDiscovery(false))
}
return public.New(clientID, o...)
}
// setAuthorityHost initializes the authority host for credentials. Precedence is:
// 1. cloud.Configuration.ActiveDirectoryAuthorityHost value set by user
// 2. value of AZURE_AUTHORITY_HOST
// 3. default: Azure Public Cloud
// 1. cloud.Configuration.ActiveDirectoryAuthorityHost value set by user
// 2. value of AZURE_AUTHORITY_HOST
// 3. default: Azure Public Cloud
func setAuthorityHost(cc cloud.Configuration) (string, error) {
host := cc.ActiveDirectoryAuthorityHost
if host == "" {
@ -121,6 +74,41 @@ func setAuthorityHost(cc cloud.Configuration) (string, error) {
return host, nil
}
// resolveAdditionalTenants returns a copy of tenants, simplified when tenants contains a wildcard
func resolveAdditionalTenants(tenants []string) []string {
if len(tenants) == 0 {
return nil
}
for _, t := range tenants {
// a wildcard makes all other values redundant
if t == "*" {
return []string{"*"}
}
}
cp := make([]string, len(tenants))
copy(cp, tenants)
return cp
}
// resolveTenant returns the correct tenant for a token request
func resolveTenant(defaultTenant, specified, credName string, additionalTenants []string) (string, error) {
if specified == "" || specified == defaultTenant {
return defaultTenant, nil
}
if defaultTenant == "adfs" {
return "", errors.New("ADFS doesn't support tenants")
}
if !validTenantID(specified) {
return "", errInvalidTenantID
}
for _, t := range additionalTenants {
if t == "*" || t == specified {
return specified, nil
}
}
return "", fmt.Errorf(`%s isn't configured to acquire tokens for tenant %q. To enable acquiring tokens for this tenant add it to the AdditionallyAllowedTenants on the credential options, or add "*" to allow acquiring tokens for any tenant`, credName, specified)
}
// validTenantID return true is it receives a valid tenantID, returns false otherwise
func validTenantID(tenantID string) bool {
match, err := regexp.MatchString("^[0-9a-zA-Z-.]+$", tenantID)
@ -173,7 +161,7 @@ func (p pipelineAdapter) Do(r *http.Request) (*http.Response, error) {
}
// enables fakes for test scenarios
type confidentialClient interface {
type msalConfidentialClient interface {
AcquireTokenSilent(ctx context.Context, scopes []string, options ...confidential.AcquireSilentOption) (confidential.AuthResult, error)
AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, options ...confidential.AcquireByAuthCodeOption) (confidential.AuthResult, error)
AcquireTokenByCredential(ctx context.Context, scopes []string, options ...confidential.AcquireByCredentialOption) (confidential.AuthResult, error)
@ -181,7 +169,7 @@ type confidentialClient interface {
}
// enables fakes for test scenarios
type publicClient interface {
type msalPublicClient interface {
AcquireTokenSilent(ctx context.Context, scopes []string, options ...public.AcquireSilentOption) (public.AuthResult, error)
AcquireTokenByUsernamePassword(ctx context.Context, scopes []string, username string, password string, options ...public.AcquireByUsernamePasswordOption) (public.AuthResult, error)
AcquireTokenByDeviceCode(ctx context.Context, scopes []string, options ...public.AcquireByDeviceCodeOption) (public.DeviceCode, error)

129
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go сгенерированный поставляемый
Просмотреть файл

@ -17,10 +17,12 @@ import (
"regexp"
"runtime"
"strings"
"sync"
"time"
"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/internal/log"
)
const (
@ -47,14 +49,14 @@ type AzureCLICredentialOptions struct {
// init returns an instance of AzureCLICredentialOptions initialized with default values.
func (o *AzureCLICredentialOptions) init() {
if o.tokenProvider == nil {
o.tokenProvider = defaultTokenProvider()
o.tokenProvider = defaultTokenProvider
}
}
// AzureCLICredential authenticates as the identity logged in to the Azure CLI.
type AzureCLICredential struct {
s *syncer
tokenProvider azureCLITokenProvider
mu *sync.Mutex
opts AzureCLICredentialOptions
}
// NewAzureCLICredential constructs an AzureCLICredential. Pass nil to accept default options.
@ -64,9 +66,8 @@ func NewAzureCLICredential(options *AzureCLICredentialOptions) (*AzureCLICredent
cp = *options
}
cp.init()
c := AzureCLICredential{tokenProvider: cp.tokenProvider}
c.s = newSyncer(credNameAzureCLI, cp.TenantID, cp.AdditionallyAllowedTenants, c.requestToken, c.requestToken)
return &c, nil
cp.AdditionallyAllowedTenants = resolveAdditionalTenants(cp.AdditionallyAllowedTenants)
return &AzureCLICredential{mu: &sync.Mutex{}, opts: cp}, nil
}
// GetToken requests a token from the Azure CLI. This credential doesn't cache tokens, so every call invokes the CLI.
@ -75,13 +76,15 @@ func (c *AzureCLICredential) GetToken(ctx context.Context, opts policy.TokenRequ
if len(opts.Scopes) != 1 {
return azcore.AccessToken{}, errors.New(credNameAzureCLI + ": GetToken() requires exactly one scope")
}
// CLI expects an AAD v1 resource, not a v2 scope
tenant, err := resolveTenant(c.opts.TenantID, opts.TenantID, credNameAzureCLI, c.opts.AdditionallyAllowedTenants)
if err != nil {
return azcore.AccessToken{}, err
}
// pass the CLI an AAD v1 resource because we don't know which CLI version is installed and older ones don't support v2 scopes
opts.Scopes = []string{strings.TrimSuffix(opts.Scopes[0], defaultSuffix)}
return c.s.GetToken(ctx, opts)
}
func (c *AzureCLICredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
b, err := c.tokenProvider(ctx, opts.Scopes[0], opts.TenantID)
c.mu.Lock()
defer c.mu.Unlock()
b, err := c.opts.tokenProvider(ctx, opts.Scopes[0], tenant)
if err != nil {
return azcore.AccessToken{}, err
}
@ -89,61 +92,61 @@ func (c *AzureCLICredential) requestToken(ctx context.Context, opts policy.Token
if err != nil {
return azcore.AccessToken{}, err
}
msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", credNameAzureCLI, strings.Join(opts.Scopes, ", "))
log.Write(EventAuthentication, msg)
return at, nil
}
func defaultTokenProvider() func(ctx context.Context, resource string, tenantID string) ([]byte, error) {
return func(ctx context.Context, resource string, tenantID string) ([]byte, error) {
match, err := regexp.MatchString("^[0-9a-zA-Z-.:/]+$", resource)
if err != nil {
return nil, err
}
if !match {
return nil, fmt.Errorf(`%s: unexpected scope "%s". Only alphanumeric characters and ".", ";", "-", and "/" are allowed`, credNameAzureCLI, resource)
}
// set a default timeout for this authentication iff the application hasn't done so already
var cancel context.CancelFunc
if _, hasDeadline := ctx.Deadline(); !hasDeadline {
ctx, cancel = context.WithTimeout(ctx, timeoutCLIRequest)
defer cancel()
}
commandLine := "az account get-access-token -o json --resource " + resource
if tenantID != "" {
commandLine += " --tenant " + tenantID
}
var cliCmd *exec.Cmd
if runtime.GOOS == "windows" {
dir := os.Getenv("SYSTEMROOT")
if dir == "" {
return nil, newCredentialUnavailableError(credNameAzureCLI, "environment variable 'SYSTEMROOT' has no value")
}
cliCmd = exec.CommandContext(ctx, "cmd.exe", "/c", commandLine)
cliCmd.Dir = dir
} else {
cliCmd = exec.CommandContext(ctx, "/bin/sh", "-c", commandLine)
cliCmd.Dir = "/bin"
}
cliCmd.Env = os.Environ()
var stderr bytes.Buffer
cliCmd.Stderr = &stderr
output, err := cliCmd.Output()
if err != nil {
msg := stderr.String()
var exErr *exec.ExitError
if errors.As(err, &exErr) && exErr.ExitCode() == 127 || strings.HasPrefix(msg, "'az' is not recognized") {
msg = "Azure CLI not found on path"
}
if msg == "" {
msg = err.Error()
}
return nil, newCredentialUnavailableError(credNameAzureCLI, msg)
}
return output, nil
var defaultTokenProvider azureCLITokenProvider = func(ctx context.Context, resource string, tenantID string) ([]byte, error) {
match, err := regexp.MatchString("^[0-9a-zA-Z-.:/]+$", resource)
if err != nil {
return nil, err
}
if !match {
return nil, fmt.Errorf(`%s: unexpected scope "%s". Only alphanumeric characters and ".", ";", "-", and "/" are allowed`, credNameAzureCLI, resource)
}
// set a default timeout for this authentication iff the application hasn't done so already
var cancel context.CancelFunc
if _, hasDeadline := ctx.Deadline(); !hasDeadline {
ctx, cancel = context.WithTimeout(ctx, timeoutCLIRequest)
defer cancel()
}
commandLine := "az account get-access-token -o json --resource " + resource
if tenantID != "" {
commandLine += " --tenant " + tenantID
}
var cliCmd *exec.Cmd
if runtime.GOOS == "windows" {
dir := os.Getenv("SYSTEMROOT")
if dir == "" {
return nil, newCredentialUnavailableError(credNameAzureCLI, "environment variable 'SYSTEMROOT' has no value")
}
cliCmd = exec.CommandContext(ctx, "cmd.exe", "/c", commandLine)
cliCmd.Dir = dir
} else {
cliCmd = exec.CommandContext(ctx, "/bin/sh", "-c", commandLine)
cliCmd.Dir = "/bin"
}
cliCmd.Env = os.Environ()
var stderr bytes.Buffer
cliCmd.Stderr = &stderr
output, err := cliCmd.Output()
if err != nil {
msg := stderr.String()
var exErr *exec.ExitError
if errors.As(err, &exErr) && exErr.ExitCode() == 127 || strings.HasPrefix(msg, "'az' is not recognized") {
msg = "Azure CLI not found on path"
}
if msg == "" {
msg = err.Error()
}
return nil, newCredentialUnavailableError(credNameAzureCLI, msg)
}
return output, nil
}
func (c *AzureCLICredential) createAccessToken(tk []byte) (azcore.AccessToken, error) {

25
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml сгенерированный поставляемый
Просмотреть файл

@ -26,22 +26,9 @@ stages:
parameters:
RunLiveTests: true
ServiceDirectory: 'azidentity'
PreSteps:
- pwsh: |
[System.Convert]::FromBase64String($env:PFX_CONTENTS) | Set-Content -Path $(Agent.TempDirectory)/test.pfx -AsByteStream
Set-Content -Path $(Agent.TempDirectory)/test.pem -Value $env:PEM_CONTENTS
[System.Convert]::FromBase64String($env:SNI_CONTENTS) | Set-Content -Path $(Agent.TempDirectory)/testsni.pfx -AsByteStream
env:
PFX_CONTENTS: $(net-identity-spcert-pfx)
PEM_CONTENTS: $(net-identity-spcert-pem)
SNI_CONTENTS: $(net-identity-spcert-sni)
EnvVars:
AZURE_IDENTITY_TEST_TENANTID: $(net-identity-tenantid)
AZURE_IDENTITY_TEST_USERNAME: $(net-identity-username)
AZURE_IDENTITY_TEST_PASSWORD: $(net-identity-password)
IDENTITY_SP_TENANT_ID: $(net-identity-sp-tenantid)
IDENTITY_SP_CLIENT_ID: $(net-identity-sp-clientid)
IDENTITY_SP_CLIENT_SECRET: $(net-identity-sp-clientsecret)
IDENTITY_SP_CERT_PEM: $(Agent.TempDirectory)/test.pem
IDENTITY_SP_CERT_PFX: $(Agent.TempDirectory)/test.pfx
IDENTITY_SP_CERT_SNI: $(Agent.TempDirectory)/testsni.pfx
CloudConfig:
Public:
SubscriptionConfigurations:
- $(sub-config-azure-cloud-test-resources)
# Contains alternate tenant, AAD app and cert info for testing
- $(sub-config-identity-test-resources)

26
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go сгенерированный поставляемый
Просмотреть файл

@ -24,8 +24,7 @@ const credNameAssertion = "ClientAssertionCredential"
//
// [Azure AD documentation]: https://docs.microsoft.com/azure/active-directory/develop/active-directory-certificate-credentials#assertion-format
type ClientAssertionCredential struct {
client confidentialClient
s *syncer
client *confidentialClient
}
// ClientAssertionCredentialOptions contains optional parameters for ClientAssertionCredential.
@ -56,28 +55,21 @@ func NewClientAssertionCredential(tenantID, clientID string, getAssertion func(c
return getAssertion(ctx)
},
)
c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery))
msalOpts := confidentialClientOptions{
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
ClientOptions: options.ClientOptions,
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
}
c, err := newConfidentialClient(tenantID, clientID, credNameAssertion, cred, msalOpts)
if err != nil {
return nil, err
}
cac := ClientAssertionCredential{client: c}
cac.s = newSyncer(credNameAssertion, tenantID, options.AdditionallyAllowedTenants, cac.requestToken, cac.silentAuth)
return &cac, nil
return &ClientAssertionCredential{client: c}, nil
}
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
func (c *ClientAssertionCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
return c.s.GetToken(ctx, opts)
}
func (c *ClientAssertionCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
func (c *ClientAssertionCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenByCredential(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
return c.client.GetToken(ctx, opts)
}
var _ azcore.TokenCredential = (*ClientAssertionCredential)(nil)

30
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go сгенерированный поставляемый
Просмотреть файл

@ -42,8 +42,7 @@ type ClientCertificateCredentialOptions struct {
// ClientCertificateCredential authenticates a service principal with a certificate.
type ClientCertificateCredential struct {
client confidentialClient
s *syncer
client *confidentialClient
}
// NewClientCertificateCredential constructs a ClientCertificateCredential. Pass nil for options to accept defaults.
@ -58,33 +57,22 @@ func NewClientCertificateCredential(tenantID string, clientID string, certs []*x
if err != nil {
return nil, err
}
var o []confidential.Option
if options.SendCertificateChain {
o = append(o, confidential.WithX5C())
msalOpts := confidentialClientOptions{
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
ClientOptions: options.ClientOptions,
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
SendX5C: options.SendCertificateChain,
}
o = append(o, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery))
c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions, o...)
c, err := newConfidentialClient(tenantID, clientID, credNameCert, cred, msalOpts)
if err != nil {
return nil, err
}
cc := ClientCertificateCredential{client: c}
cc.s = newSyncer(credNameCert, tenantID, options.AdditionallyAllowedTenants, cc.requestToken, cc.silentAuth)
return &cc, nil
return &ClientCertificateCredential{client: c}, nil
}
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
func (c *ClientCertificateCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
return c.s.GetToken(ctx, opts)
}
func (c *ClientCertificateCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
func (c *ClientCertificateCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenByCredential(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
return c.client.GetToken(ctx, opts)
}
// ParseCertificates loads certificates and a private key, in PEM or PKCS12 format, for use with NewClientCertificateCredential.

28
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go сгенерированный поставляемый
Просмотреть файл

@ -33,8 +33,7 @@ type ClientSecretCredentialOptions struct {
// ClientSecretCredential authenticates an application with a client secret.
type ClientSecretCredential struct {
client confidentialClient
s *syncer
client *confidentialClient
}
// NewClientSecretCredential constructs a ClientSecretCredential. Pass nil for options to accept defaults.
@ -46,30 +45,21 @@ func NewClientSecretCredential(tenantID string, clientID string, clientSecret st
if err != nil {
return nil, err
}
c, err := getConfidentialClient(
clientID, tenantID, cred, &options.ClientOptions, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery),
)
msalOpts := confidentialClientOptions{
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
ClientOptions: options.ClientOptions,
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
}
c, err := newConfidentialClient(tenantID, clientID, credNameSecret, cred, msalOpts)
if err != nil {
return nil, err
}
csc := ClientSecretCredential{client: c}
csc.s = newSyncer(credNameSecret, tenantID, options.AdditionallyAllowedTenants, csc.requestToken, csc.silentAuth)
return &csc, nil
return &ClientSecretCredential{c}, nil
}
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
func (c *ClientSecretCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
return c.s.GetToken(ctx, opts)
}
func (c *ClientSecretCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
func (c *ClientSecretCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenByCredential(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
return c.client.GetToken(ctx, opts)
}
var _ azcore.TokenCredential = (*ClientSecretCredential)(nil)

156
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/confidential_client.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,156 @@
//go:build go1.18
// +build go1.18
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package azidentity
import (
"context"
"errors"
"fmt"
"os"
"strings"
"sync"
"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/azcore/runtime"
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
)
type confidentialClientOptions struct {
azcore.ClientOptions
AdditionallyAllowedTenants []string
// Assertion for on-behalf-of authentication
Assertion string
DisableInstanceDiscovery, SendX5C bool
}
// confidentialClient wraps the MSAL confidential client
type confidentialClient struct {
cae, noCAE msalConfidentialClient
caeMu, noCAEMu, clientMu *sync.Mutex
clientID, tenantID string
cred confidential.Credential
host string
name string
opts confidentialClientOptions
region string
}
func newConfidentialClient(tenantID, clientID, name string, cred confidential.Credential, opts confidentialClientOptions) (*confidentialClient, error) {
if !validTenantID(tenantID) {
return nil, errInvalidTenantID
}
host, err := setAuthorityHost(opts.Cloud)
if err != nil {
return nil, err
}
opts.AdditionallyAllowedTenants = resolveAdditionalTenants(opts.AdditionallyAllowedTenants)
return &confidentialClient{
caeMu: &sync.Mutex{},
clientID: clientID,
clientMu: &sync.Mutex{},
cred: cred,
host: host,
name: name,
noCAEMu: &sync.Mutex{},
opts: opts,
region: os.Getenv(azureRegionalAuthorityName),
tenantID: tenantID,
}, nil
}
// GetToken requests an access token from MSAL, checking the cache first.
func (c *confidentialClient) GetToken(ctx context.Context, tro policy.TokenRequestOptions) (azcore.AccessToken, error) {
if len(tro.Scopes) < 1 {
return azcore.AccessToken{}, fmt.Errorf("%s.GetToken() requires at least one scope", c.name)
}
// we don't resolve the tenant for managed identities because they acquire tokens only from their home tenants
if c.name != credNameManagedIdentity {
tenant, err := c.resolveTenant(tro.TenantID)
if err != nil {
return azcore.AccessToken{}, err
}
tro.TenantID = tenant
}
client, mu, err := c.client(ctx, tro)
if err != nil {
return azcore.AccessToken{}, err
}
mu.Lock()
defer mu.Unlock()
var ar confidential.AuthResult
if c.opts.Assertion != "" {
ar, err = client.AcquireTokenOnBehalfOf(ctx, c.opts.Assertion, tro.Scopes, confidential.WithClaims(tro.Claims), confidential.WithTenantID(tro.TenantID))
} else {
ar, err = client.AcquireTokenSilent(ctx, tro.Scopes, confidential.WithClaims(tro.Claims), confidential.WithTenantID(tro.TenantID))
if err != nil {
ar, err = client.AcquireTokenByCredential(ctx, tro.Scopes, confidential.WithClaims(tro.Claims), confidential.WithTenantID(tro.TenantID))
}
}
if err != nil {
// We could get a credentialUnavailableError from managed identity authentication because in that case the error comes from our code.
// We return it directly because it affects the behavior of credential chains. Otherwise, we return AuthenticationFailedError.
var unavailableErr *credentialUnavailableError
if !errors.As(err, &unavailableErr) {
res := getResponseFromError(err)
err = newAuthenticationFailedError(c.name, err.Error(), res, err)
}
} else {
msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", c.name, strings.Join(ar.GrantedScopes, ", "))
log.Write(EventAuthentication, msg)
}
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
func (c *confidentialClient) client(ctx context.Context, tro policy.TokenRequestOptions) (msalConfidentialClient, *sync.Mutex, error) {
c.clientMu.Lock()
defer c.clientMu.Unlock()
if tro.EnableCAE {
if c.cae == nil {
client, err := c.newMSALClient(true)
if err != nil {
return nil, nil, err
}
c.cae = client
}
return c.cae, c.caeMu, nil
}
if c.noCAE == nil {
client, err := c.newMSALClient(false)
if err != nil {
return nil, nil, err
}
c.noCAE = client
}
return c.noCAE, c.noCAEMu, nil
}
func (c *confidentialClient) newMSALClient(enableCAE bool) (msalConfidentialClient, error) {
authority := runtime.JoinPaths(c.host, c.tenantID)
o := []confidential.Option{
confidential.WithAzureRegion(c.region),
confidential.WithHTTPClient(newPipelineAdapter(&c.opts.ClientOptions)),
}
if enableCAE {
o = append(o, confidential.WithClientCapabilities(cp1))
}
if c.opts.SendX5C {
o = append(o, confidential.WithX5C())
}
if c.opts.DisableInstanceDiscovery || strings.ToLower(c.tenantID) == "adfs" {
o = append(o, confidential.WithInstanceDiscovery(false))
}
return confidential.New(authority, c.clientID, c.cred, o...)
}
// resolveTenant returns the correct tenant for a token request given the client's
// configuration, or an error when that configuration doesn't allow the specified tenant
func (c *confidentialClient) resolveTenant(specified string) (string, error) {
return resolveTenant(c.tenantID, specified, c.name, c.opts.AdditionallyAllowedTenants)
}

29
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go сгенерированный поставляемый
Просмотреть файл

@ -21,6 +21,8 @@ import (
// DefaultAzureCredentialOptions contains optional parameters for DefaultAzureCredential.
// These options may not apply to all credentials in the chain.
type DefaultAzureCredentialOptions struct {
// ClientOptions has additional options for credentials that use an Azure SDK HTTP pipeline. These options don't apply
// to credential types that authenticate via external tools such as the Azure CLI.
azcore.ClientOptions
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens. Add
@ -32,8 +34,7 @@ type DefaultAzureCredentialOptions struct {
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
// the application responsible for ensuring the configured authority is valid and trustworthy.
DisableInstanceDiscovery bool
// TenantID identifies the tenant the Azure CLI should authenticate in.
// Defaults to the CLI's default tenant, which is typically the home tenant of the user logged in to the CLI.
// TenantID sets the default tenant for authentication via the Azure CLI and workload identity.
TenantID string
}
@ -83,11 +84,11 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
creds = append(creds, &defaultCredentialErrorReporter{credType: "EnvironmentCredential", err: err})
}
// workload identity requires values for AZURE_AUTHORITY_HOST, AZURE_CLIENT_ID, AZURE_FEDERATED_TOKEN_FILE, AZURE_TENANT_ID
wic, err := NewWorkloadIdentityCredential(&WorkloadIdentityCredentialOptions{
AdditionallyAllowedTenants: additionalTenants,
ClientOptions: options.ClientOptions,
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
TenantID: options.TenantID,
})
if err == nil {
creds = append(creds, wic)
@ -95,6 +96,7 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
errorMessages = append(errorMessages, credNameWorkloadIdentity+": "+err.Error())
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameWorkloadIdentity, err: err})
}
o := &ManagedIdentityCredentialOptions{ClientOptions: options.ClientOptions}
if ID, ok := os.LookupEnv(azureClientID); ok {
o.ID = ClientID(ID)
@ -115,9 +117,8 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameAzureCLI, err: err})
}
err = defaultAzureCredentialConstructorErrorHandler(len(creds), errorMessages)
if err != nil {
return nil, err
if len(errorMessages) > 0 {
log.Writef(EventAuthentication, "NewDefaultAzureCredential failed to initialize some credentials:\n\t%s", strings.Join(errorMessages, "\n\t"))
}
chain, err := NewChainedTokenCredential(creds, nil)
@ -135,20 +136,6 @@ func (c *DefaultAzureCredential) GetToken(ctx context.Context, opts policy.Token
var _ azcore.TokenCredential = (*DefaultAzureCredential)(nil)
func defaultAzureCredentialConstructorErrorHandler(numberOfSuccessfulCredentials int, errorMessages []string) (err error) {
errorMessage := strings.Join(errorMessages, "\n\t")
if numberOfSuccessfulCredentials == 0 {
return errors.New(errorMessage)
}
if len(errorMessages) != 0 {
log.Writef(EventAuthentication, "NewDefaultAzureCredential failed to initialize some credentials:\n\t%s", errorMessage)
}
return nil
}
// defaultCredentialErrorReporter is a substitute for credentials that couldn't be constructed.
// Its GetToken method always returns a credentialUnavailableError having the same message as
// the error that prevented constructing the credential. This ensures the message is present
@ -185,7 +172,7 @@ func (w *timeoutWrapper) GetToken(ctx context.Context, opts policy.TokenRequestO
defer cancel()
tk, err = w.mic.GetToken(c, opts)
if isAuthFailedDueToContext(err) {
err = newCredentialUnavailableError(credNameManagedIdentity, "managed identity timed out")
err = newCredentialUnavailableError(credNameManagedIdentity, "managed identity timed out. See https://aka.ms/azsdk/go/identity/troubleshoot#dac for more information")
} else {
// some managed identity implementation is available, so don't apply the timeout to future calls
w.timeout = 0

52
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go сгенерированный поставляемый
Просмотреть файл

@ -12,7 +12,6 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
)
const credNameDeviceCode = "DeviceCodeCredential"
@ -74,10 +73,7 @@ type DeviceCodeMessage struct {
// If a web browser is available, InteractiveBrowserCredential is more convenient because it
// automatically opens a browser to the login page.
type DeviceCodeCredential struct {
account public.Account
client publicClient
s *syncer
prompt func(context.Context, DeviceCodeMessage) error
client *publicClient
}
// NewDeviceCodeCredential creates a DeviceCodeCredential. Pass nil to accept default options.
@ -87,50 +83,24 @@ func NewDeviceCodeCredential(options *DeviceCodeCredentialOptions) (*DeviceCodeC
cp = *options
}
cp.init()
c, err := getPublicClient(
cp.ClientID, cp.TenantID, &cp.ClientOptions, public.WithInstanceDiscovery(!cp.DisableInstanceDiscovery),
)
msalOpts := publicClientOptions{
AdditionallyAllowedTenants: cp.AdditionallyAllowedTenants,
ClientOptions: cp.ClientOptions,
DeviceCodePrompt: cp.UserPrompt,
DisableInstanceDiscovery: cp.DisableInstanceDiscovery,
}
c, err := newPublicClient(cp.TenantID, cp.ClientID, credNameDeviceCode, msalOpts)
if err != nil {
return nil, err
}
cred := DeviceCodeCredential{client: c, prompt: cp.UserPrompt}
cred.s = newSyncer(credNameDeviceCode, cp.TenantID, cp.AdditionallyAllowedTenants, cred.requestToken, cred.silentAuth)
return &cred, nil
c.name = credNameDeviceCode
return &DeviceCodeCredential{client: c}, nil
}
// GetToken requests an access token from Azure Active Directory. It will begin the device code flow and poll until the user completes authentication.
// This method is called automatically by Azure SDK clients.
func (c *DeviceCodeCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
return c.s.GetToken(ctx, opts)
}
func (c *DeviceCodeCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
dc, err := c.client.AcquireTokenByDeviceCode(ctx, opts.Scopes, public.WithTenantID(opts.TenantID))
if err != nil {
return azcore.AccessToken{}, err
}
err = c.prompt(ctx, DeviceCodeMessage{
Message: dc.Result.Message,
UserCode: dc.Result.UserCode,
VerificationURL: dc.Result.VerificationURL,
})
if err != nil {
return azcore.AccessToken{}, err
}
ar, err := dc.AuthenticationResult(ctx)
if err != nil {
return azcore.AccessToken{}, err
}
c.account = ar.Account
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
func (c *DeviceCodeCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes,
public.WithSilentAccount(c.account),
public.WithTenantID(opts.TenantID),
)
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
return c.client.GetToken(ctx, opts)
}
var _ azcore.TokenCredential = (*DeviceCodeCredential)(nil)

13
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go сгенерированный поставляемый
Просмотреть файл

@ -11,9 +11,9 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
"github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo"
msal "github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors"
)
@ -57,17 +57,16 @@ func (e *AuthenticationFailedError) Error() string {
fmt.Fprintln(msg, "--------------------------------------------------------------------------------")
fmt.Fprintf(msg, "RESPONSE %s\n", e.RawResponse.Status)
fmt.Fprintln(msg, "--------------------------------------------------------------------------------")
body, err := io.ReadAll(e.RawResponse.Body)
e.RawResponse.Body.Close()
if err != nil {
body, err := runtime.Payload(e.RawResponse)
switch {
case err != nil:
fmt.Fprintf(msg, "Error reading response body: %v", err)
} else if len(body) > 0 {
e.RawResponse.Body = io.NopCloser(bytes.NewReader(body))
case len(body) > 0:
if err := json.Indent(msg, body, "", " "); err != nil {
// failed to pretty-print so just dump it verbatim
fmt.Fprint(msg, string(body))
}
} else {
default:
fmt.Fprint(msg, "Response contained no body")
}
fmt.Fprintln(msg, "\n--------------------------------------------------------------------------------")

40
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/interactive_browser_credential.go сгенерированный поставляемый
Просмотреть файл

@ -11,7 +11,6 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
)
const credNameBrowser = "InteractiveBrowserCredential"
@ -56,10 +55,7 @@ func (o *InteractiveBrowserCredentialOptions) init() {
// InteractiveBrowserCredential opens a browser to interactively authenticate a user.
type InteractiveBrowserCredential struct {
account public.Account
client publicClient
options InteractiveBrowserCredentialOptions
s *syncer
client *publicClient
}
// NewInteractiveBrowserCredential constructs a new InteractiveBrowserCredential. Pass nil to accept default options.
@ -69,38 +65,22 @@ func NewInteractiveBrowserCredential(options *InteractiveBrowserCredentialOption
cp = *options
}
cp.init()
c, err := getPublicClient(cp.ClientID, cp.TenantID, &cp.ClientOptions, public.WithInstanceDiscovery(!cp.DisableInstanceDiscovery))
msalOpts := publicClientOptions{
ClientOptions: cp.ClientOptions,
DisableInstanceDiscovery: cp.DisableInstanceDiscovery,
LoginHint: cp.LoginHint,
RedirectURL: cp.RedirectURL,
}
c, err := newPublicClient(cp.TenantID, cp.ClientID, credNameBrowser, msalOpts)
if err != nil {
return nil, err
}
ibc := InteractiveBrowserCredential{client: c, options: cp}
ibc.s = newSyncer(credNameBrowser, cp.TenantID, cp.AdditionallyAllowedTenants, ibc.requestToken, ibc.silentAuth)
return &ibc, nil
return &InteractiveBrowserCredential{client: c}, nil
}
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
func (c *InteractiveBrowserCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
return c.s.GetToken(ctx, opts)
}
func (c *InteractiveBrowserCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenInteractive(ctx, opts.Scopes,
public.WithLoginHint(c.options.LoginHint),
public.WithRedirectURI(c.options.RedirectURL),
public.WithTenantID(opts.TenantID),
)
if err == nil {
c.account = ar.Account
}
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
func (c *InteractiveBrowserCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes,
public.WithSilentAccount(c.account),
public.WithTenantID(opts.TenantID),
)
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
return c.client.GetToken(ctx, opts)
}
var _ azcore.TokenCredential = (*InteractiveBrowserCredential)(nil)

28
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go сгенерированный поставляемый
Просмотреть файл

@ -84,13 +84,15 @@ func setIMDSRetryOptionDefaults(o *policy.RetryOptions) {
}
if o.StatusCodes == nil {
o.StatusCodes = []int{
// IMDS docs recommend retrying 404, 429 and all 5xx
// https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#error-handling
// IMDS docs recommend retrying 404, 410, 429 and 5xx
// https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#error-handling
http.StatusNotFound, // 404
http.StatusGone, // 410
http.StatusTooManyRequests, // 429
http.StatusInternalServerError, // 500
http.StatusNotImplemented, // 501
http.StatusBadGateway, // 502
http.StatusServiceUnavailable, // 503
http.StatusGatewayTimeout, // 504
http.StatusHTTPVersionNotSupported, // 505
http.StatusVariantAlsoNegotiates, // 506
@ -175,11 +177,25 @@ func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKi
return c.createAccessToken(resp)
}
if c.msiType == msiTypeIMDS && resp.StatusCode == 400 {
if id != nil {
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "the requested identity isn't assigned to this resource", resp, nil)
if c.msiType == msiTypeIMDS {
switch resp.StatusCode {
case http.StatusBadRequest:
if id != nil {
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "the requested identity isn't assigned to this resource", resp, nil)
}
msg := "failed to authenticate a system assigned identity"
if body, err := runtime.Payload(resp); err == nil && len(body) > 0 {
msg += fmt.Sprintf(". The endpoint responded with %s", body)
}
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, msg)
case http.StatusForbidden:
// Docker Desktop runs a proxy that responds 403 to IMDS token requests. If we get that response,
// we return credentialUnavailableError so credential chains continue to their next credential
body, err := runtime.Payload(resp)
if err == nil && strings.Contains(string(body), "A socket operation was attempted to an unreachable network") {
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, fmt.Sprintf("unexpected response %q", string(body)))
}
}
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, "no default identity is assigned to this resource")
}
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "authentication failed", resp, nil)

26
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go сгенерированный поставляемый
Просмотреть файл

@ -8,7 +8,6 @@ package azidentity
import (
"context"
"errors"
"fmt"
"strings"
@ -71,9 +70,8 @@ type ManagedIdentityCredentialOptions struct {
// user-assigned identity. See Azure Active Directory documentation for more information about managed identities:
// https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview
type ManagedIdentityCredential struct {
client confidentialClient
client *confidentialClient
mic *managedIdentityClient
s *syncer
}
// NewManagedIdentityCredential creates a ManagedIdentityCredential. Pass nil to accept default options.
@ -93,35 +91,23 @@ func NewManagedIdentityCredential(options *ManagedIdentityCredentialOptions) (*M
if options.ID != nil {
clientID = options.ID.String()
}
// similarly, it's okay to give MSAL an incorrect authority URL because that URL won't be used
c, err := confidential.New("https://login.microsoftonline.com/common", clientID, cred)
// similarly, it's okay to give MSAL an incorrect tenant because MSAL won't use the value
c, err := newConfidentialClient("common", clientID, credNameManagedIdentity, cred, confidentialClientOptions{})
if err != nil {
return nil, err
}
m := ManagedIdentityCredential{client: c, mic: mic}
m.s = newSyncer(credNameManagedIdentity, "", nil, m.requestToken, m.silentAuth)
return &m, nil
return &ManagedIdentityCredential{client: c, mic: mic}, nil
}
// GetToken requests an access token from the hosting environment. This method is called automatically by Azure SDK clients.
func (c *ManagedIdentityCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
if len(opts.Scopes) != 1 {
err := errors.New(credNameManagedIdentity + ": GetToken() requires exactly one scope")
err := fmt.Errorf("%s.GetToken() requires exactly one scope", credNameManagedIdentity)
return azcore.AccessToken{}, err
}
// managed identity endpoints require an AADv1 resource (i.e. token audience), not a v2 scope, so we remove "/.default" here
opts.Scopes = []string{strings.TrimSuffix(opts.Scopes[0], defaultSuffix)}
return c.s.GetToken(ctx, opts)
}
func (c *ManagedIdentityCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenByCredential(ctx, opts.Scopes)
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
func (c *ManagedIdentityCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes)
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
return c.client.GetToken(ctx, opts)
}
var _ azcore.TokenCredential = (*ManagedIdentityCredential)(nil)

27
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/on_behalf_of_credential.go сгенерированный поставляемый
Просмотреть файл

@ -25,9 +25,7 @@ const credNameOBO = "OnBehalfOfCredential"
//
// [Azure Active Directory documentation]: https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow
type OnBehalfOfCredential struct {
assertion string
client confidentialClient
s *syncer
client *confidentialClient
}
// OnBehalfOfCredentialOptions contains optional parameters for OnBehalfOfCredential
@ -72,28 +70,23 @@ func newOnBehalfOfCredential(tenantID, clientID, userAssertion string, cred conf
if options == nil {
options = &OnBehalfOfCredentialOptions{}
}
opts := []confidential.Option{}
if options.SendCertificateChain {
opts = append(opts, confidential.WithX5C())
opts := confidentialClientOptions{
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
Assertion: userAssertion,
ClientOptions: options.ClientOptions,
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
SendX5C: options.SendCertificateChain,
}
opts = append(opts, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery))
c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions, opts...)
c, err := newConfidentialClient(tenantID, clientID, credNameOBO, cred, opts)
if err != nil {
return nil, err
}
obo := OnBehalfOfCredential{assertion: userAssertion, client: c}
obo.s = newSyncer(credNameOBO, tenantID, options.AdditionallyAllowedTenants, obo.requestToken, obo.requestToken)
return &obo, nil
return &OnBehalfOfCredential{c}, nil
}
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
func (o *OnBehalfOfCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
return o.s.GetToken(ctx, opts)
}
func (o *OnBehalfOfCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := o.client.AcquireTokenOnBehalfOf(ctx, o.assertion, opts.Scopes, confidential.WithTenantID(opts.TenantID))
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
return o.client.GetToken(ctx, opts)
}
var _ azcore.TokenCredential = (*OnBehalfOfCredential)(nil)

178
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/public_client.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,178 @@
//go:build go1.18
// +build go1.18
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package azidentity
import (
"context"
"fmt"
"strings"
"sync"
"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/azcore/runtime"
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
)
type publicClientOptions struct {
azcore.ClientOptions
AdditionallyAllowedTenants []string
DeviceCodePrompt func(context.Context, DeviceCodeMessage) error
DisableInstanceDiscovery bool
LoginHint, RedirectURL string
Username, Password string
}
// publicClient wraps the MSAL public client
type publicClient struct {
account public.Account
cae, noCAE msalPublicClient
caeMu, noCAEMu, clientMu *sync.Mutex
clientID, tenantID string
host string
name string
opts publicClientOptions
}
func newPublicClient(tenantID, clientID, name string, o publicClientOptions) (*publicClient, error) {
if !validTenantID(tenantID) {
return nil, errInvalidTenantID
}
host, err := setAuthorityHost(o.Cloud)
if err != nil {
return nil, err
}
o.AdditionallyAllowedTenants = resolveAdditionalTenants(o.AdditionallyAllowedTenants)
return &publicClient{
caeMu: &sync.Mutex{},
clientID: clientID,
clientMu: &sync.Mutex{},
host: host,
name: name,
noCAEMu: &sync.Mutex{},
opts: o,
tenantID: tenantID,
}, nil
}
// GetToken requests an access token from MSAL, checking the cache first.
func (p *publicClient) GetToken(ctx context.Context, tro policy.TokenRequestOptions) (azcore.AccessToken, error) {
if len(tro.Scopes) < 1 {
return azcore.AccessToken{}, fmt.Errorf("%s.GetToken() requires at least one scope", p.name)
}
tenant, err := p.resolveTenant(tro.TenantID)
if err != nil {
return azcore.AccessToken{}, err
}
client, mu, err := p.client(tro)
if err != nil {
return azcore.AccessToken{}, err
}
mu.Lock()
defer mu.Unlock()
ar, err := client.AcquireTokenSilent(ctx, tro.Scopes, public.WithSilentAccount(p.account), public.WithClaims(tro.Claims), public.WithTenantID(tenant))
if err == nil {
return p.token(ar, err)
}
at, err := p.reqToken(ctx, client, tro)
if err == nil {
msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", p.name, strings.Join(ar.GrantedScopes, ", "))
log.Write(EventAuthentication, msg)
}
return at, err
}
// reqToken requests a token from the MSAL public client. It's separate from GetToken() to enable Authenticate() to bypass the cache.
func (p *publicClient) reqToken(ctx context.Context, c msalPublicClient, tro policy.TokenRequestOptions) (azcore.AccessToken, error) {
tenant, err := p.resolveTenant(tro.TenantID)
if err != nil {
return azcore.AccessToken{}, err
}
var ar public.AuthResult
switch p.name {
case credNameBrowser:
ar, err = c.AcquireTokenInteractive(ctx, tro.Scopes,
public.WithClaims(tro.Claims),
public.WithLoginHint(p.opts.LoginHint),
public.WithRedirectURI(p.opts.RedirectURL),
public.WithTenantID(tenant),
)
case credNameDeviceCode:
dc, e := c.AcquireTokenByDeviceCode(ctx, tro.Scopes, public.WithClaims(tro.Claims), public.WithTenantID(tenant))
if e != nil {
return azcore.AccessToken{}, e
}
err = p.opts.DeviceCodePrompt(ctx, DeviceCodeMessage{
Message: dc.Result.Message,
UserCode: dc.Result.UserCode,
VerificationURL: dc.Result.VerificationURL,
})
if err == nil {
ar, err = dc.AuthenticationResult(ctx)
}
case credNameUserPassword:
ar, err = c.AcquireTokenByUsernamePassword(ctx, tro.Scopes, p.opts.Username, p.opts.Password, public.WithClaims(tro.Claims), public.WithTenantID(tenant))
default:
return azcore.AccessToken{}, fmt.Errorf("unknown credential %q", p.name)
}
return p.token(ar, err)
}
func (p *publicClient) client(tro policy.TokenRequestOptions) (msalPublicClient, *sync.Mutex, error) {
p.clientMu.Lock()
defer p.clientMu.Unlock()
if tro.EnableCAE {
if p.cae == nil {
client, err := p.newMSALClient(true)
if err != nil {
return nil, nil, err
}
p.cae = client
}
return p.cae, p.caeMu, nil
}
if p.noCAE == nil {
client, err := p.newMSALClient(false)
if err != nil {
return nil, nil, err
}
p.noCAE = client
}
return p.noCAE, p.noCAEMu, nil
}
func (p *publicClient) newMSALClient(enableCAE bool) (msalPublicClient, error) {
o := []public.Option{
public.WithAuthority(runtime.JoinPaths(p.host, p.tenantID)),
public.WithHTTPClient(newPipelineAdapter(&p.opts.ClientOptions)),
}
if enableCAE {
o = append(o, public.WithClientCapabilities(cp1))
}
if p.opts.DisableInstanceDiscovery || strings.ToLower(p.tenantID) == "adfs" {
o = append(o, public.WithInstanceDiscovery(false))
}
return public.New(p.clientID, o...)
}
func (p *publicClient) token(ar public.AuthResult, err error) (azcore.AccessToken, error) {
if err == nil {
p.account = ar.Account
} else {
res := getResponseFromError(err)
err = newAuthenticationFailedError(p.name, err.Error(), res, err)
}
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
// resolveTenant returns the correct tenant for a token request given the client's
// configuration, or an error when that configuration doesn't allow the specified tenant
func (p *publicClient) resolveTenant(specified string) (string, error) {
return resolveTenant(p.tenantID, specified, p.name, p.opts.AdditionallyAllowedTenants)
}

130
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/syncer.go сгенерированный поставляемый
Просмотреть файл

@ -1,130 +0,0 @@
//go:build go1.18
// +build go1.18
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package azidentity
import (
"context"
"errors"
"fmt"
"strings"
"sync"
"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/internal/log"
)
type authFn func(context.Context, policy.TokenRequestOptions) (azcore.AccessToken, error)
// syncer synchronizes authentication calls so that goroutines can share a credential instance
type syncer struct {
addlTenants []string
authing bool
cond *sync.Cond
reqToken, silent authFn
name, tenant string
}
func newSyncer(name, tenant string, additionalTenants []string, reqToken, silentAuth authFn) *syncer {
return &syncer{
addlTenants: resolveAdditionalTenants(additionalTenants),
cond: &sync.Cond{L: &sync.Mutex{}},
name: name,
reqToken: reqToken,
silent: silentAuth,
tenant: tenant,
}
}
// GetToken ensures that only one goroutine authenticates at a time
func (s *syncer) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
var at azcore.AccessToken
var err error
if len(opts.Scopes) == 0 {
return at, errors.New(s.name + ".GetToken() requires at least one scope")
}
// we don't resolve the tenant for managed identities because they can acquire tokens only from their home tenants
if s.name != credNameManagedIdentity {
tenant, err := s.resolveTenant(opts.TenantID)
if err != nil {
return at, err
}
opts.TenantID = tenant
}
auth := false
s.cond.L.Lock()
defer s.cond.L.Unlock()
for {
at, err = s.silent(ctx, opts)
if err == nil {
// got a token
break
}
if !s.authing {
// this goroutine will request a token
s.authing, auth = true, true
break
}
// another goroutine is acquiring a token; wait for it to finish, then try silent auth again
s.cond.Wait()
}
if auth {
s.authing = false
at, err = s.reqToken(ctx, opts)
s.cond.Broadcast()
}
if err != nil {
// Return credentialUnavailableError directly because that type affects the behavior of credential chains.
// Otherwise, return AuthenticationFailedError.
var unavailableErr *credentialUnavailableError
if !errors.As(err, &unavailableErr) {
res := getResponseFromError(err)
err = newAuthenticationFailedError(s.name, err.Error(), res, err)
}
} else if log.Should(EventAuthentication) {
scope := strings.Join(opts.Scopes, ", ")
msg := fmt.Sprintf(`%s.GetToken() acquired a token for scope "%s"\n`, s.name, scope)
log.Write(EventAuthentication, msg)
}
return at, err
}
// resolveTenant returns the correct tenant for a token request given the credential's
// configuration, or an error when the specified tenant isn't allowed by that configuration
func (s *syncer) resolveTenant(requested string) (string, error) {
if requested == "" || requested == s.tenant {
return s.tenant, nil
}
if s.tenant == "adfs" {
return "", errors.New("ADFS doesn't support tenants")
}
if !validTenantID(requested) {
return "", errors.New(tenantIDValidationErr)
}
for _, t := range s.addlTenants {
if t == "*" || t == requested {
return requested, nil
}
}
return "", fmt.Errorf(`%s isn't configured to acquire tokens for tenant %q. To enable acquiring tokens for this tenant add it to the AdditionallyAllowedTenants on the credential options, or add "*" to allow acquiring tokens for any tenant`, s.name, requested)
}
// resolveAdditionalTenants returns a copy of tenants, simplified when tenants contains a wildcard
func resolveAdditionalTenants(tenants []string) []string {
if len(tenants) == 0 {
return nil
}
for _, t := range tenants {
// a wildcard makes all other values redundant
if t == "*" {
return []string{"*"}
}
}
cp := make([]string, len(tenants))
copy(cp, tenants)
return cp
}

36
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-pre.ps1 сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,36 @@
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
param (
# Captures any arguments from eng/New-TestResources.ps1 not declared here (no parameter errors).
[Parameter(ValueFromRemainingArguments = $true)]
$RemainingArguments
)
if (!$CI) {
# TODO: Remove this once auto-cloud config downloads are supported locally
Write-Host "Skipping cert setup in local testing mode"
return
}
if ($EnvironmentVariables -eq $null -or $EnvironmentVariables.Count -eq 0) {
throw "EnvironmentVariables must be set in the calling script New-TestResources.ps1"
}
$tmp = $env:TEMP ? $env:TEMP : [System.IO.Path]::GetTempPath()
$pfxPath = Join-Path $tmp "test.pfx"
$pemPath = Join-Path $tmp "test.pem"
$sniPath = Join-Path $tmp "testsni.pfx"
Write-Host "Creating identity test files: $pfxPath $pemPath $sniPath"
[System.Convert]::FromBase64String($EnvironmentVariables['PFX_CONTENTS']) | Set-Content -Path $pfxPath -AsByteStream
Set-Content -Path $pemPath -Value $EnvironmentVariables['PEM_CONTENTS']
[System.Convert]::FromBase64String($EnvironmentVariables['SNI_CONTENTS']) | Set-Content -Path $sniPath -AsByteStream
# Set for pipeline
Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_PFX;]$pfxPath"
Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_PEM;]$pemPath"
Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_SNI;]$sniPath"
# Set for local
$env:IDENTITY_SP_CERT_PFX = $pfxPath
$env:IDENTITY_SP_CERT_PEM = $pemPath
$env:IDENTITY_SP_CERT_SNI = $sniPath

1
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
param baseName string

37
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go сгенерированный поставляемый
Просмотреть файл

@ -11,7 +11,6 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
)
const credNameUserPassword = "UsernamePasswordCredential"
@ -36,10 +35,7 @@ type UsernamePasswordCredentialOptions struct {
// with any form of multi-factor authentication, and the application must already have user or admin consent.
// This credential can only authenticate work and school accounts; it can't authenticate Microsoft accounts.
type UsernamePasswordCredential struct {
account public.Account
client publicClient
password, username string
s *syncer
client *publicClient
}
// NewUsernamePasswordCredential creates a UsernamePasswordCredential. clientID is the ID of the application the user
@ -48,34 +44,23 @@ func NewUsernamePasswordCredential(tenantID string, clientID string, username st
if options == nil {
options = &UsernamePasswordCredentialOptions{}
}
c, err := getPublicClient(clientID, tenantID, &options.ClientOptions, public.WithInstanceDiscovery(!options.DisableInstanceDiscovery))
opts := publicClientOptions{
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
ClientOptions: options.ClientOptions,
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
Password: password,
Username: username,
}
c, err := newPublicClient(tenantID, clientID, credNameUserPassword, opts)
if err != nil {
return nil, err
}
upc := UsernamePasswordCredential{client: c, password: password, username: username}
upc.s = newSyncer(credNameUserPassword, tenantID, options.AdditionallyAllowedTenants, upc.requestToken, upc.silentAuth)
return &upc, nil
return &UsernamePasswordCredential{client: c}, err
}
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
func (c *UsernamePasswordCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
return c.s.GetToken(ctx, opts)
}
func (c *UsernamePasswordCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenByUsernamePassword(ctx, opts.Scopes, c.username, c.password, public.WithTenantID(opts.TenantID))
if err == nil {
c.account = ar.Account
}
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
func (c *UsernamePasswordCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes,
public.WithSilentAccount(c.account),
public.WithTenantID(opts.TenantID),
)
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
return c.client.GetToken(ctx, opts)
}
var _ azcore.TokenCredential = (*UsernamePasswordCredential)(nil)

2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go сгенерированный поставляемый
Просмотреть файл

@ -11,5 +11,5 @@ const (
component = "azidentity"
// Version is the semantic version (see http://semver.org) of this module.
version = "v1.3.1"
version = "v1.4.0"
)

4
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go сгенерированный поставляемый
Просмотреть файл

@ -47,7 +47,7 @@ type WorkloadIdentityCredentialOptions struct {
DisableInstanceDiscovery bool
// TenantID of the service principal. Defaults to the value of the environment variable AZURE_TENANT_ID.
TenantID string
// TokenFilePath is the path a file containing the workload identity token. Defaults to the value of the
// TokenFilePath is the path of a file containing a Kubernetes service account token. Defaults to the value of the
// environment variable AZURE_FEDERATED_TOKEN_FILE.
TokenFilePath string
}
@ -88,7 +88,7 @@ func NewWorkloadIdentityCredential(options *WorkloadIdentityCredentialOptions) (
return nil, err
}
// we want "WorkloadIdentityCredential" in log messages, not "ClientAssertionCredential"
cred.s.name = credNameWorkloadIdentity
cred.client.name = credNameWorkloadIdentity
w.cred = cred
return &w, nil
}

83
vendor/github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault/CHANGELOG.md сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,83 @@
# Release History
## 1.4.0 (2023-11-24)
### Features Added
- Support for test fakes and OpenTelemetry trace spans.
## 1.3.0 (2023-10-27)
### Features Added
- New value `ManagedHsmSKUNameCustomB6` added to enum type `ManagedHsmSKUName`
- New enum type `ManagedServiceIdentityType` with values `ManagedServiceIdentityTypeNone`, `ManagedServiceIdentityTypeSystemAssigned`, `ManagedServiceIdentityTypeSystemAssignedUserAssigned`, `ManagedServiceIdentityTypeUserAssigned`
- New struct `ManagedServiceIdentity`
- New struct `UserAssignedIdentity`
- New field `Identity` in struct `MHSMPrivateEndpointConnection`
- New field `Identity` in struct `MHSMPrivateLinkResource`
- New field `Identity` in struct `ManagedHsm`
## 1.2.0 (2023-04-28)
### Features Added
- New value `JSONWebKeyOperationRelease` added to enum type `JSONWebKeyOperation`
- New value `KeyPermissionsGetrotationpolicy`, `KeyPermissionsRelease`, `KeyPermissionsRotate`, `KeyPermissionsSetrotationpolicy` added to enum type `KeyPermissions`
- New enum type `ActivationStatus` with values `ActivationStatusActive`, `ActivationStatusFailed`, `ActivationStatusNotActivated`, `ActivationStatusUnknown`
- New enum type `GeoReplicationRegionProvisioningState` with values `GeoReplicationRegionProvisioningStateCleanup`, `GeoReplicationRegionProvisioningStateDeleting`, `GeoReplicationRegionProvisioningStateFailed`, `GeoReplicationRegionProvisioningStatePreprovisioning`, `GeoReplicationRegionProvisioningStateProvisioning`, `GeoReplicationRegionProvisioningStateSucceeded`
- New enum type `KeyRotationPolicyActionType` with values `KeyRotationPolicyActionTypeNotify`, `KeyRotationPolicyActionTypeRotate`
- New function `*ClientFactory.NewMHSMRegionsClient() *MHSMRegionsClient`
- New function `*ClientFactory.NewManagedHsmKeysClient() *ManagedHsmKeysClient`
- New function `NewMHSMRegionsClient(string, azcore.TokenCredential, *arm.ClientOptions) (*MHSMRegionsClient, error)`
- New function `*MHSMRegionsClient.NewListByResourcePager(string, string, *MHSMRegionsClientListByResourceOptions) *runtime.Pager[MHSMRegionsClientListByResourceResponse]`
- New function `NewManagedHsmKeysClient(string, azcore.TokenCredential, *arm.ClientOptions) (*ManagedHsmKeysClient, error)`
- New function `*ManagedHsmKeysClient.CreateIfNotExist(context.Context, string, string, string, ManagedHsmKeyCreateParameters, *ManagedHsmKeysClientCreateIfNotExistOptions) (ManagedHsmKeysClientCreateIfNotExistResponse, error)`
- New function `*ManagedHsmKeysClient.Get(context.Context, string, string, string, *ManagedHsmKeysClientGetOptions) (ManagedHsmKeysClientGetResponse, error)`
- New function `*ManagedHsmKeysClient.GetVersion(context.Context, string, string, string, string, *ManagedHsmKeysClientGetVersionOptions) (ManagedHsmKeysClientGetVersionResponse, error)`
- New function `*ManagedHsmKeysClient.NewListPager(string, string, *ManagedHsmKeysClientListOptions) *runtime.Pager[ManagedHsmKeysClientListResponse]`
- New function `*ManagedHsmKeysClient.NewListVersionsPager(string, string, string, *ManagedHsmKeysClientListVersionsOptions) *runtime.Pager[ManagedHsmKeysClientListVersionsResponse]`
- New function `*ManagedHsmsClient.CheckMhsmNameAvailability(context.Context, CheckMhsmNameAvailabilityParameters, *ManagedHsmsClientCheckMhsmNameAvailabilityOptions) (ManagedHsmsClientCheckMhsmNameAvailabilityResponse, error)`
- New struct `Action`
- New struct `CheckMhsmNameAvailabilityParameters`
- New struct `CheckMhsmNameAvailabilityResult`
- New struct `KeyReleasePolicy`
- New struct `KeyRotationPolicyAttributes`
- New struct `LifetimeAction`
- New struct `MHSMGeoReplicatedRegion`
- New struct `MHSMRegionsListResult`
- New struct `ManagedHSMSecurityDomainProperties`
- New struct `ManagedHsmAction`
- New struct `ManagedHsmKey`
- New struct `ManagedHsmKeyAttributes`
- New struct `ManagedHsmKeyCreateParameters`
- New struct `ManagedHsmKeyListResult`
- New struct `ManagedHsmKeyProperties`
- New struct `ManagedHsmKeyReleasePolicy`
- New struct `ManagedHsmKeyRotationPolicyAttributes`
- New struct `ManagedHsmLifetimeAction`
- New struct `ManagedHsmRotationPolicy`
- New struct `ManagedHsmTrigger`
- New struct `ProxyResourceWithoutSystemData`
- New struct `RotationPolicy`
- New struct `Trigger`
- New field `ReleasePolicy` in struct `KeyProperties`
- New field `RotationPolicy` in struct `KeyProperties`
- New field `Etag` in struct `MHSMPrivateEndpointConnectionItem`
- New field `ID` in struct `MHSMPrivateEndpointConnectionItem`
- New field `Regions` in struct `ManagedHsmProperties`
- New field `SecurityDomainProperties` in struct `ManagedHsmProperties`
## 1.1.0 (2023-04-06)
### Features Added
- New struct `ClientFactory` which is a client factory used to create any client in this module
## 1.0.0 (2022-05-16)
The package of `github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault` is using our [next generation design principles](https://azure.github.io/azure-sdk/general_introduction.html) since version 1.0.0, which contains breaking changes.
To migrate the existing applications to the latest version, please refer to [Migration Guide](https://aka.ms/azsdk/go/mgmt/migration).
To learn more, please refer to our documentation [Quick Start](https://aka.ms/azsdk/go/mgmt).

21
vendor/github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault/LICENSE.txt сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

98
vendor/github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault/README.md сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,98 @@
# Azure Key Vault Module for Go
[![PkgGoDev](https://pkg.go.dev/badge/github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault)](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault)
The `armkeyvault` module provides operations for working with Azure Key Vault.
[Source code](https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/resourcemanager/keyvault/armkeyvault)
# Getting started
## Prerequisites
- an [Azure subscription](https://azure.microsoft.com/free/)
- Go 1.18 or above (You could download and install the latest version of Go from [here](https://go.dev/doc/install). It will replace the existing Go on your machine. If you want to install multiple Go versions on the same machine, you could refer this [doc](https://go.dev/doc/manage-install).)
## Install the package
This project uses [Go modules](https://github.com/golang/go/wiki/Modules) for versioning and dependency management.
Install the Azure Key Vault module:
```sh
go get github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault
```
## Authorization
When creating a client, you will need to provide a credential for authenticating with Azure Key Vault. The `azidentity` module provides facilities for various ways of authenticating with Azure including client/secret, certificate, managed identity, and more.
```go
cred, err := azidentity.NewDefaultAzureCredential(nil)
```
For more information on authentication, please see the documentation for `azidentity` at [pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity).
## Client Factory
Azure Key Vault module consists of one or more clients. We provide a client factory which could be used to create any client in this module.
```go
clientFactory, err := armkeyvault.NewClientFactory(<subscription ID>, cred, nil)
```
You can use `ClientOptions` in package `github.com/Azure/azure-sdk-for-go/sdk/azcore/arm` to set endpoint to connect with public and sovereign clouds as well as Azure Stack. For more information, please see the documentation for `azcore` at [pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore).
```go
options := arm.ClientOptions {
ClientOptions: azcore.ClientOptions {
Cloud: cloud.AzureChina,
},
}
clientFactory, err := armkeyvault.NewClientFactory(<subscription ID>, cred, &options)
```
## Clients
A client groups a set of related APIs, providing access to its functionality. Create one or more clients to access the APIs you require using client factory.
```go
client := clientFactory.NewVaultsClient()
```
## Fakes
The fake package contains types used for constructing in-memory fake servers used in unit tests.
This allows writing tests to cover various success/error conditions without the need for connecting to a live service.
Please see https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/samples/fakes for details and examples on how to use fakes.
## More sample code
- [Key](https://aka.ms/azsdk/go/mgmt/samples?path=sdk/resourcemanager/keyvault/key)
- [Secret](https://aka.ms/azsdk/go/mgmt/samples?path=sdk/resourcemanager/keyvault/secret)
- [Vault](https://aka.ms/azsdk/go/mgmt/samples?path=sdk/resourcemanager/keyvault/vault)
## Provide Feedback
If you encounter bugs or have suggestions, please
[open an issue](https://github.com/Azure/azure-sdk-for-go/issues) and assign the `Key Vault` label.
# Contributing
This project welcomes contributions and suggestions. Most contributions require
you to agree to a Contributor License Agreement (CLA) declaring that you have
the right to, and actually do, grant us the rights to use your contribution.
For details, visit [https://cla.microsoft.com](https://cla.microsoft.com).
When you submit a pull request, a CLA-bot will automatically determine whether
you need to provide a CLA and decorate the PR appropriately (e.g., label,
comment). Simply follow the instructions provided by the bot. You will only
need to do this once across all repos using our CLA.
This project has adopted the
[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information, see the
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any
additional questions or comments.

6
vendor/github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault/assets.json сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
{
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "go",
"TagPrefix": "go/resourcemanager/keyvault/armkeyvault",
"Tag": "go/resourcemanager/keyvault/armkeyvault_820248387e"
}

15
vendor/github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault/autorest.md сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
### AutoRest Configuration
> see https://aka.ms/autorest
``` yaml
azure-arm: true
require:
- https://github.com/Azure/azure-rest-api-specs/blob/9ec0fcc278aa2128c4fbb2b8a1aa93432d72cce0/specification/keyvault/resource-manager/readme.md
- https://github.com/Azure/azure-rest-api-specs/blob/9ec0fcc278aa2128c4fbb2b8a1aa93432d72cce0/specification/keyvault/resource-manager/readme.go.md
license-header: MICROSOFT_MIT_NO_VERSION
module-version: 1.4.0
modelerfour:
seal-single-value-enum-by-default: true
tag: package-2023-07
```

7
vendor/github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault/build.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// This file enables 'go generate' to regenerate this specific SDK
//go:generate pwsh ../../../../eng/scripts/build.ps1 -skipBuild -cleanGenerated -format -tidy -generate -removeUnreferencedTypes resourcemanager/keyvault/armkeyvault
package armkeyvault

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше