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 PowerShell Deployment Script #92

Merged
merged 5 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
],
"env": {
"AZURE_LOCATION": "West Europe",
"VAULT_ADDR": "http://localhost:62293/",
//"VAULT_TOKEN": "PLEASE_ADD_VAULT_TOKEN"",
"VAULT_ADDR": "http://localhost:54969/",
//"VAULT_TOKEN": "PLEASE_ADD_VAULT_TOKEN"",
"AZURE_MANAGED_IDENTITY_RG": "global",
"AZURE_MANAGED_IDENTITY_NAME": "scriptidentity",
//"RUSI_ENABLED": "true"
//"PULUMI_SKIP_REFRESH": "true",
},
Expand Down
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,51 @@ spec:
workspaceFriendlyName: Charisma
```

### AzurePowershellScript
`AzurePowershellScript` is a Custom Resource Definition (CRD) that represents an Azure PowerShell deployment script.

Definition can be found [here](./helm/crds/provisioning.totalsoft.ro_azurepowershellscripts.yaml)

#### Spec
The `AzurePowershellScript` spec has the following fields:

- `scriptContent`: The content of the PowerShell script to be executed.
- `scriptArguments`: The arguments to be passed to the PowerShell script. These should match the parameters defined in the scriptContent.
- `domainRef`: The reference to the domain that the user belongs to.
- `platformRef`: The reference to the platform that the user belongs to.
- `forceUpdateTag`: Update this value to trigger the script even if the content or args are unchanged

Example:
```yaml
apiVersion: provisioning.totalsoft.ro/v1alpha1
kind: AzurePowerShellScript
metadata:
name: createresourcegroup
namespace: provisioning-test
spec:
domainRef: domain2
exports:
- scriptOutputs:
toConfigMap:
keyTemplate: MultiTenancy__Tenants__{{ .Tenant.Code }}__ScriptOutputs
platformRef: provisioning.test
scriptContent: |-
param([string] $name)

$output = "RG name: {0}" -f $name
Write-Output $output

$DeploymentScriptOutputs = @{}
$DeploymentScriptOutputs['text'] = $output

New-AzResourceGroup $name "West Europe"
scriptArguments: "-name testrg-{{ .Platform }}-{{ .Tenant.Code }}"
target:
category: Tenant
```



### EntraUser

`EntraUser` is a Custom Resource Definition (CRD) that represents a user for Entra Id.
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/pulumi/pulumi-azure-native-sdk/authorization/v2 v2.4.0
github.com/pulumi/pulumi-azure-native-sdk/compute/v2 v2.4.0
github.com/pulumi/pulumi-azure-native-sdk/desktopvirtualization/v2 v2.4.0
github.com/pulumi/pulumi-azure-native-sdk/managedidentity/v2 v2.4.0
github.com/pulumi/pulumi-azure-native-sdk/network/v2 v2.4.0
github.com/pulumi/pulumi-azure-native-sdk/resources/v2 v2.4.0
github.com/pulumi/pulumi-azure-native-sdk/sql/v2 v2.4.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ github.com/pulumi/pulumi-azure-native-sdk/compute/v2 v2.4.0 h1:h6SVlNPqa8Spxya7G
github.com/pulumi/pulumi-azure-native-sdk/compute/v2 v2.4.0/go.mod h1:eD5kkSSQU2kJbW7telpS9gaM6hiRH4Q8u4lcOpx8jrc=
github.com/pulumi/pulumi-azure-native-sdk/desktopvirtualization/v2 v2.4.0 h1:pz8cmyWEFE4qfGGDBAGMQ35pWckM2OOSxgY1cK9e4JI=
github.com/pulumi/pulumi-azure-native-sdk/desktopvirtualization/v2 v2.4.0/go.mod h1:s7GSMVekCyCrWTEA3aOdVDtOVkIqTW0yrMnWlWG+4V8=
github.com/pulumi/pulumi-azure-native-sdk/managedidentity/v2 v2.4.0 h1:94XmWZiARdqexr5Sm+PW+tnxQ0VT5lRIXxrWO/WcHJQ=
github.com/pulumi/pulumi-azure-native-sdk/managedidentity/v2 v2.4.0/go.mod h1:JT+ptHaDSxTWwZYmnwKCewX8imIsBE5c49gryfOI5nY=
github.com/pulumi/pulumi-azure-native-sdk/network/v2 v2.4.0 h1:KrMG6wvPQuBEqbECNotGBWEuhEEoArN9ndcdkKIzWIY=
github.com/pulumi/pulumi-azure-native-sdk/network/v2 v2.4.0/go.mod h1:vszGWHBWdeTWzIIHR7ka04NGQh0GHyVK/yhAbtIEnA4=
github.com/pulumi/pulumi-azure-native-sdk/resources/v2 v2.4.0 h1:xqKfg8BZSQxZFrTtj06Qjjro7yyOiep58+N6hszLSJE=
Expand Down
166 changes: 166 additions & 0 deletions helm/crds/provisioning.totalsoft.ro_azurepowershellscripts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.14.0
name: azurepowershellscripts.provisioning.totalsoft.ro
spec:
group: provisioning.totalsoft.ro
names:
kind: AzurePowerShellScript
listKind: AzurePowerShellScriptList
plural: azurepowershellscripts
singular: azurepowershellscript
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.platformRef
name: Platform
type: string
- jsonPath: .spec.domainRef
name: Domain
type: string
name: v1alpha1
schema:
openAPIV3Schema:
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
properties:
dependsOn:
description: List of dependencies
items:
properties:
kind:
description: Kind is a string value representing the REST resource
this dependency represents.
type: string
name:
description: ' The name of the dependency.'
type: string
required:
- kind
- name
type: object
type: array
domainRef:
description: Business Domain that this resource is provision for.
type: string
exports:
description: Export provisioning values spec.
items:
properties:
domain:
description: The domain or bounded-context in which this script
will be used.
type: string
scriptOutputs:
description: Represents the outputs of the Azure PowerShell
script.
properties:
toConfigMap:
properties:
keyTemplate:
type: string
required:
- keyTemplate
type: object
toVault:
properties:
keyTemplate:
type: string
required:
- keyTemplate
type: object
type: object
type: object
type: array
forceUpdateTag:
description: Change value to force the script to execute even if it
has not changed.
type: string
platformRef:
description: Target platform (custom resource name).
type: string
scriptArguments:
description: |-
Represents the arguments to be passed to the PowerShell script.
eg: "-name JohnDoe"
type: string
scriptContent:
description: ScriptContent represents the content of an Azure PowerShell
script.
type: string
target:
default:
category: Tenant
description: The provisioning target.
properties:
category:
default: Tenant
description: 'Provisioning target type. Possible values: Tenant,
Platform'
enum:
- Tenant
- Platform
type: string
filter:
description: |-
Filter targets (applies for category "Tenant").
If ommited all targets are selected.
properties:
kind:
default: Blacklist
description: 'Includes or excludes the speciffied targets.
Possibile values: Blacklist, Whitelist'
enum:
- Blacklist
- Whitelist
type: string
values:
description: A list of targets to include or exculde
items:
type: string
type: array
required:
- kind
type: object
required:
- category
type: object
tenantOverrides:
additionalProperties:
x-kubernetes-preserve-unknown-fields: true
description: |-
Overrides for tenants. Dictionary with tenant name as key, spec override as value.
The spec override has the same structure as Spec
type: object
required:
- domainRef
- platformRef
- scriptContent
- target
type: object
required:
- spec
type: object
served: true
storage: true
subresources: {}
4 changes: 1 addition & 3 deletions helm/crds/provisioning.totalsoft.ro_entrausers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ spec:
items:
properties:
domain:
description: The domain or bounded-context in which this database
description: The domain or bounded-context in which this user
will be used.
type: string
initialPassword:
Expand Down Expand Up @@ -117,8 +117,6 @@ spec:
- keyTemplate
type: object
type: object
required:
- domain
type: object
type: array
initialPassword:
Expand Down
10 changes: 10 additions & 0 deletions helm/templates/provisioner-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ spec:
configMapKeyRef:
name: azure-config
key: tenantId
- name: AZURE_MANAGED_IDENTITY_RG
valueFrom:
configMapKeyRef:
name: azure-config
key: managedIdentityRG
- name: AZURE_MANAGED_IDENTITY_NAME
valueFrom:
configMapKeyRef:
name: azure-config
key: managedIdentityName
- name: ARM_CLIENT_ID
valueFrom:
configMapKeyRef:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package pulumi

import (
"encoding/json"
"os"

"github.com/pulumi/pulumi-azure-native-sdk/managedidentity/v2"
"github.com/pulumi/pulumi-azure-native-sdk/resources/v2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"totalsoft.ro/platform-controllers/internal/controllers/provisioning"
"totalsoft.ro/platform-controllers/internal/template"
provisioningv1 "totalsoft.ro/platform-controllers/pkg/apis/provisioning/v1alpha1"
)

func deployAzurePowerShellScript(target provisioning.ProvisioningTarget,
resourceGroupName pulumi.StringOutput,
azurePowerShellScript *provisioningv1.AzurePowerShellScript,
dependencies []pulumi.Resource,
ctx *pulumi.Context) (*resources.AzurePowerShellScript, error) {

valueExporter := handleValueExport(target)
gvk := provisioningv1.SchemeGroupVersion.WithKind("AzurePowerShellScript")

tc := provisioning.GetTemplateContext(target)

parsedArgs, err := template.ParseTemplate(azurePowerShellScript.Spec.ScriptArguments, tc)
if err != nil {
return nil, err
}

managedIdentity, err := managedidentity.LookupUserAssignedIdentity(ctx, &managedidentity.LookupUserAssignedIdentityArgs{
ResourceGroupName: os.Getenv("AZURE_MANAGED_IDENTITY_RG"),
ResourceName: os.Getenv("AZURE_MANAGED_IDENTITY_NAME"),
})

if err != nil {
return nil, err
}

script, err := resources.NewAzurePowerShellScript(ctx, azurePowerShellScript.Name, &resources.AzurePowerShellScriptArgs{
Kind: pulumi.String("AzurePowerShell"),
ForceUpdateTag: pulumi.String(azurePowerShellScript.Spec.ForceUpdateTag), // Change to force redeploying the script if desired
ResourceGroupName: resourceGroupName,
Arguments: pulumi.String(parsedArgs), // Set the arguments for the script'"),
ScriptContent: pulumi.String(azurePowerShellScript.Spec.ScriptContent),
CleanupPreference: pulumi.String("OnSuccess"), // Set the cleanup preference for the script
Timeout: pulumi.String("PT1H"), // Set an appropriate timeout for the script
Identity: &resources.ManagedServiceIdentityArgs{
Type: pulumi.String(resources.ManagedServiceIdentityTypeUserAssigned),
UserAssignedIdentities: pulumi.StringArray{
pulumi.String(managedIdentity.Id),
},
},
AzPowerShellVersion: pulumi.String("11.0"), // Specify the desired version of Az PowerShell module
RetentionInterval: pulumi.String("P1D"), // Set the retention time for the script's logs
})
if err != nil {
return nil, err
}

for _, exp := range azurePowerShellScript.Spec.Exports {
domain := exp.Domain
if domain == "" {
domain = azurePowerShellScript.Spec.DomainRef
}

err = valueExporter(newExportContext(ctx, domain, azurePowerShellScript.Name, azurePowerShellScript.ObjectMeta, gvk),

map[string]exportTemplateWithValue{"scriptOutputs": {exp.ScriptOutputs, script.Outputs.ApplyT(func(outputs map[string]interface{}) (string, error) {
outputsJson, err := json.Marshal(outputs)
if err != nil {
return "", err
}

return string(outputsJson), err
}).(pulumi.StringOutput)}})
if err != nil {
return nil, err
}
}
return script, nil
}
Loading
Loading