Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Azure Entra PIM custom resource #3663

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Draft
78 changes: 78 additions & 0 deletions examples/examples_nodejs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@
package examples

import (
"context"
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"

"github.com/pulumi/pulumi/pkg/v3/testing/integration"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2"
)

func TestAccAppServiceTs(t *testing.T) {
Expand Down Expand Up @@ -308,6 +313,79 @@ func TestPortalDashboardTs(t *testing.T) {
integration.ProgramTest(t, &test)
}

func TestAccPIMRoleManagementPolicies(t *testing.T) {
skipIfShort(t)

// A randomly chosen Role Management Policy, from the list obtained by
// az rest --method get --url https://management.azure.com/subscriptions/0282681f-7a9e-424b-80b2-96babd57a8a1/providers/Microsoft.Authorization/roleManagementPolicies\?api-version\=2020-10-01
const policyId = "7ed63469-c833-4fba-9032-803ce289eabc"

// Retrieve the `maximumDuration` property of the randomly chosen Expiration_Admin_Eligibility rule.
// Used in ExtraRuntimeValidation to assert that the rule has the expected duration.
// Uses the Azure SDK to be able to retrieve the actual value from Azure, independent of Pulumi.
get_Expiration_Admin_Eligibility_RuleDuration := func() string {
cred, err := azidentity.NewClientSecretCredential(
os.Getenv("ARM_TENANT_ID"),
os.Getenv("ARM_CLIENT_ID"),
os.Getenv("ARM_CLIENT_SECRET"),
nil)
require.NoError(t, err)

sub := os.Getenv("ARM_SUBSCRIPTION_ID")
clientFactory, err := armauthorization.NewClientFactory(sub, cred, nil)
require.NoError(t, err)
client := clientFactory.NewRoleManagementPoliciesClient()

resp, err := client.Get(context.Background(), "subscriptions/"+sub, policyId, nil)
require.NoError(t, err)

var rule *armauthorization.RoleManagementPolicyExpirationRule
for _, r := range resp.RoleManagementPolicy.Properties.Rules {
if *r.GetRoleManagementPolicyRule().ID != "Expiration_Admin_Eligibility" {
continue
}
var castOk bool
rule, castOk = r.(*armauthorization.RoleManagementPolicyExpirationRule)
require.True(t, castOk, "%T", r)
break
}
assert.NotNil(t, rule)
return *(rule.MaximumDuration)
}

initialDuration := get_Expiration_Admin_Eligibility_RuleDuration()

test := getJSBaseOptions(t).
With(integration.ProgramTestOptions{
DebugLogLevel: 9,
Verbose: true,
Dir: filepath.Join(getCwd(t), "pim-rolemanagementpolicies"),
Config: map[string]string{"policy": policyId},
ExpectRefreshChanges: false,
ExtraRuntimeValidation: func(t *testing.T, stackInfo integration.RuntimeValidationStackInfo) {
assert.Equal(t, "P365D", get_Expiration_Admin_Eligibility_RuleDuration())
},
EditDirs: []integration.EditDir{
{
Dir: filepath.Join("pim-rolemanagementpolicies", "2-update-rule"),
Additive: true,
ExtraRuntimeValidation: func(t *testing.T, stackInfo integration.RuntimeValidationStackInfo) {
assert.Equal(t, "P90D", get_Expiration_Admin_Eligibility_RuleDuration())
},
},
{
Dir: filepath.Join("pim-rolemanagementpolicies", "3-remove-rule"),
Additive: true,
ExtraRuntimeValidation: func(t *testing.T, stackInfo integration.RuntimeValidationStackInfo) {
assert.Equal(t, initialDuration, get_Expiration_Admin_Eligibility_RuleDuration())
},
},
},
})

integration.ProgramTest(t, &test)
}

func getJSBaseOptions(t *testing.T) integration.ProgramTestOptions {
base := getBaseOptions(t)
baseJS := base.With(integration.ProgramTestOptions{
Expand Down
3 changes: 2 additions & 1 deletion examples/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module github.com/pulumi/pulumi-azure-native/examples
go 1.23

require (
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0
github.com/pulumi/examples/misc/test v0.0.0-20240224092907-9f1d92c3e166
github.com/pulumi/pulumi-azure-native-sdk/resources/v2 v2.28.0
github.com/pulumi/pulumi-azure-native-sdk/servicebus/v2 v2.28.0
Expand All @@ -22,7 +24,6 @@ require (
cloud.google.com/go/storage v1.39.1 // indirect
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions examples/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0 h1:Hp+EScFOu9HeCbeW8WU2yQPJd4gGwhMgKxWe+G6jNzw=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0/go.mod h1:/pz8dyNQe+Ey3yBp/XuYz7oqX8YDNWVpPB0hH3XWfbc=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
Expand Down
2 changes: 2 additions & 0 deletions examples/pim-rolemanagementpolicies/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
/node_modules/
17 changes: 17 additions & 0 deletions examples/pim-rolemanagementpolicies/2-update-rule/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as pulumi from "@pulumi/pulumi";
import * as pim from "@pulumi/azure-native/authorization";

const clientConfig = pulumi.output(pim.getClientConfig());

const policy = new pim.RoleManagementPolicy("policy", {
roleManagementPolicyName: new pulumi.Config().requireSecret("policy"),
scope: pulumi.interpolate`subscriptions/${clientConfig.subscriptionId}`,
rules: [
{
"id": "Expiration_Admin_Eligibility",
"maximumDuration": "P90D", // new
"isExpirationRequired": true,
"ruleType": "RoleManagementPolicyExpirationRule",
},
]
});
22 changes: 22 additions & 0 deletions examples/pim-rolemanagementpolicies/3-remove-rule/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as pulumi from "@pulumi/pulumi";
import * as pim from "@pulumi/azure-native/authorization";

const clientConfig = pulumi.output(pim.getClientConfig());

const policy = new pim.RoleManagementPolicy("policy", {
roleManagementPolicyName: new pulumi.Config().requireSecret("policy"),
scope: pulumi.interpolate`subscriptions/${clientConfig.subscriptionId}`,
rules: [
// rule removed, but it will still exist in Azure

// we add another one since an empty list is not allowed
{
"id": "Notification_Admin_Admin_Eligibility",
"isDefaultRecipientsEnabled": true,
"notificationLevel": "All",
"notificationType": "Email",
"recipientType": "Admin",
"ruleType": "RoleManagementPolicyNotificationRule",
},
]
});
7 changes: 7 additions & 0 deletions examples/pim-rolemanagementpolicies/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: pim-rolemanagementpolicies
runtime: nodejs
description: A minimal Azure Native TypeScript Pulumi program
config:
pulumi:tags:
value:
pulumi:template: ""
17 changes: 17 additions & 0 deletions examples/pim-rolemanagementpolicies/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as pulumi from "@pulumi/pulumi";
import * as pim from "@pulumi/azure-native/authorization";

const clientConfig = pulumi.output(pim.getClientConfig());

const policy = new pim.RoleManagementPolicy("policy", {
roleManagementPolicyName: new pulumi.Config().requireSecret("policy"),
scope: pulumi.interpolate`subscriptions/${clientConfig.subscriptionId}`,
rules: [
{
"id": "Expiration_Admin_Eligibility",
"isExpirationRequired": true,
"maximumDuration": "P365D",
"ruleType": "RoleManagementPolicyExpirationRule",
},
]
});
11 changes: 11 additions & 0 deletions examples/pim-rolemanagementpolicies/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "pim-rolemanagementpolicies",
"main": "index.ts",
"devDependencies": {
"@types/node": "^18"
},
"dependencies": {
"@pulumi/pulumi": "^3.0.0",
"@pulumi/azure-native": "^2.0.0"
}
}
18 changes: 18 additions & 0 deletions examples/pim-rolemanagementpolicies/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts",
]
}
Loading
Loading